This question follows the previous one .
Case 1: Default Type
The following program does not compile or report error C2995: 'T foo(void)': function template has already been defined:
#include <iostream>
#include <type_traits>
template < typename T, typename = std::enable_if_t< std::is_integral<T>::value> >
T foo() { std::cout << "integral" << std::endl; return T(); }
template < typename T, typename = std::enable_if_t< !std::is_integral<T>::value> >
T foo() { std::cout << "non-integral" << std::endl; return T(); }
int main() {
foo<int>();
foo<float>();
}
Each of the patterns is alternately used and ignored (SFINAE), through two instances foo. Therefore, I assume that at some point the compiler sees:
template < typename T, typename = void >
T foo() { std::cout << "integral" << std::endl; return T(); }
template < typename T, typename = void >
T foo() { std::cout << "non-integral" << std::endl; return T(); }
Both definitions are the same, and the error is somewhat understandable. Perhaps it is less clear why the compiler did not assign different names of internal functions to this point.
Case 2: default value
Now the program can be fixed, instead of using the default types, we use the default values:
template < typename T, std::enable_if_t< std::is_integral<T>::value>* = nullptr >
T foo() { std::cout << "integral" << std::endl; return T(); }
template < typename T, std::enable_if_t< !std::is_integral<T>::value>* = nullptr >
T foo() { std::cout << "non-integral" << std::endl; return T(); }
Here, following the same procedure, I get:
template < typename T, void* = nullptr >
T foo() { std::cout << "integral" << std::endl; return T(); }
template < typename T, void* = nullptr >
T foo() { std::cout << "non-integral" << std::endl; return T(); }
, , . , , , , - :
int foo_int() { std::cout << "integral" << std::endl; return int(); }
float foo_float() { std::cout << "non-integral" << std::endl; return float(); }
int main() {
foo_int();
foo_float();
}
, ?
?