隐式转换模板参数的规则

Mal*_*rba 12 c++ templates overloading

如果重载一个函数,然后使用与其中一个重载完全匹配的参数调用它

int f(int){return 3;}
int f(bool){return 4;}
...        //inside main()
f(1);      //Calls f(int)
Run Code Online (Sandbox Code Playgroud)

在尝试任何隐式转换之前,编译器只选择此(完美)匹配.但是我一直在尝试重载函数tempĺate

template <bool veracity>
int f(){return 1;}

template <int amount>
int f(){return 2;}

...        //inside main()
f<1>();
Run Code Online (Sandbox Code Playgroud)

但编译器一直抱怨对重载f()的模糊调用,说明它可能是f<true>()或者f<1>().编译器不应该只选择完美匹配,而不是尝试将1转换为true吗?

我的印象是模板参数的隐式转换实际上比函数参数的隐式转换更具限制性.有办法解决这个问题吗?

Jer*_*fin 8

您提供的参数不是类型,它是一个值,因此规则有点不同 - 您需要将规则应用于非类型参数.对于非类型参数,允许隐式转换.§14.3.2/ 5:

对用作非类型模板参数的每个表达式执行以下转换.如果非类型模板参数无法转换为相应模板参数的类型,则程序格式错误.

- 对于整数或枚举类型的非类型模板参数,将应用转换常量表达式(5.19)中允许的转换.

在C++ 03中,措辞略有不同,但效果基本相同(也是§14.3.2/ 5):

- 对于积分或枚举类型的非类型模板参数,应用积分促销(4.5)和积分转换(4.7).

无论哪种方式,因为1既是a int又可以隐式转换为a bool,你的调用是模棱两可的.


ipc*_*ipc 5

由于这不是编译器错误而是语言功能(请参阅此答案),因此您必须找到解决方法.

要么你必须重命名你的功能,要么你可以使用这个hack:

template <typename T> struct F;

template<> struct F<bool> {
  template <bool veracity>
  static int f(){return 1;}
};

template<> struct F<int> {
  template <int amount>
  static int f(){return 2;}
};

template <typename T, T value>
int f() { return F<T>::template f<value>(); }

// inside main():
std::cout << f<int,  2>() << '\n'; // prints 2
std::cout << f<bool, 2>() << '\n'; // prints 1
Run Code Online (Sandbox Code Playgroud)