函数模板之间不能重载?用默认值,或者把类型推导放到形参里,或者推到返回值类型

 默认参数的方式,不行

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 - 知乎

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值