默认参数的方式,不行
template<typename T, typename U =
std::enable_if<std::is_integral<T>::value, int>::type>
void fun1345(T t)
{
std::cout << t << std::endl;
}
template<typename T, typename U =
std::enable_if<!std::is_integral<T>::value, int>::type>
void fun1345(T t)
{
std::cout << t << std::endl;
}
还没有实际函数调用fun1345的时候,编译器就进行了报错:
C2995 “void fun1345(T)”: 函数模板已经定义
根本就没有enable_if发挥作用的机会。
原因可能是:对于函数(不是类)级别的推导。第二个参数U是个默认类型,在没有进行推导的情况下,
编辑器认为存在两个
template<typename T, typename U>
void fun1345(T t)
{
...
}
所以直接报错。
直接写成这样,也不行,还是同样的提示:
template<typename T, typename U = int>
void fun13451(T t)
{
std::cout << t << std::endl;
}
template<typename T, typename U = double>
void fun13451(T t)
{
std::cout << t << std::endl;
}
//fun1345(1);
//fun1345("123");
但,改成这样,带默认值,却可以:
template<typename T, typename
std::enable_if<std::is_integral<T>::value, int>::type=0>
void fun13451(T t)
{
std::cout << t << std::endl;
}
template<typename T, typename
std::enable_if<!std::is_integral<T>::value, int>::type = 0>
void fun13451(T t)
{
std::cout << t << std::endl;
}
调用:
{
int x = 1;
fun13451(x);
double y = 1.0;
fun13451(y);
fun13451(L"");
}
应该是推导出了三个函数:
void fun13451(int t)
{
std::cout << t << std::endl;
}
void fun13451(double t)
{
std::cout << t << std::endl;
}
void fun13451(w_char....t)//这个我手写不出来,肯定是个字符串的,类似于const wchar_t*
{
std::cout << t << std::endl;
}
看看CPPInsights怎么说:
#include <cstdio>
#include <iostream>
#include <random>
#include <utility>
#include <functional>
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
#include <string>
#include <memory>
#include <type_traits>
#include <set>
#include <map>
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void fun13451(T t)
{
(std::cout << t) << std::endl;
}
/* First instantiated from: insights.cpp:34 */ //对应fun13451(x);
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun13451<int, 0>(int t)
{
std::cout.operator<<(t).operator<<(std::endl);
}
#endif
template<typename T, typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
void fun13451(T t)
{
(std::cout << t) << std::endl;
}
/* First instantiated from: insights.cpp:36 */ //对应fun13451(y);
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun13451<double, 0>(double t)
{
std::cout.operator<<(t).operator<<(std::endl);
}
#endif
/* First instantiated from: insights.cpp:38 */ //对应fun13451(L"");
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun13451<const wchar_t *, 0>(const wchar_t * t)
{
std::cout.operator<<(t).operator<<(std::endl);
}
#endif
int main()
{
int x = 1;
fun13451(x);
double y = 1.0;
fun13451(y);
fun13451(L"");
return 0;
}
这是因为有sinfne的协助,第二个参数即使都被推导为int=0,但第一个参数可以进行区分。第二个参数只是用来进行推导。
或者,把参数推导写到形参里,改成这样就可以了:
template<typename T>
void fun1345(T t, typename std::enable_if<std::is_integral<T>::value, int>::type* = 0)
{
std::cout << t << std::endl;
}
template<typename T>
void fun1345(T t, typename std::enable_if<!std::is_integral<T>::value, int>::type* =0)
{
std::cout << t << std::endl;
}
fun1345(1);
fun1345("123");
推导返回值类型也可以:
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type div(T t) {
return t / 2;
}
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type div(T t) {
return std::floor(t / 2);
}
int main()
{
double x = div(7);
x += 0;
double y = div(7.0);
y += 0;
}
可以再看下:C++模板进阶指南:SFINAE - 知乎