将std :: enable_if从参数移动到模板参数

Sar*_*ien 5 c++ function-templates

我基本上尝试与std :: enable_if:参数vs模板参数一样,但我无法编译我的代码.

我有一个简单的第一个版本,在参数中有std :: enable_if,并且工作正常:

#include <iostream>
#include <type_traits>

template <typename T>
void foo(T t, typename std::enable_if< std::is_same<T, int>::value >::type* = 0) {
  std::cout << "int" << std::endl;
}

template <typename T>
void foo(T t, typename std::enable_if< !std::is_same<T, int>::value >::type* = 0) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但我认为如果模板的东西在一个地方并且想要函数参数中的enable_if可能会更简洁.

现在,如果我只是移动enable_if部分,我会得到以下内容:

#pragma warning(1 : 4519)

#include <iostream>
#include <type_traits>

template <typename T, typename std::enable_if< std::is_same<T, int>::value >::type = 0>
void foo(T t) {
  std::cout << "int" << std::endl;
}

template <typename T, typename std::enable_if< !std::is_same<T, int>::value >::type = 0>
void foo(T t) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

#pragma警告(1:4519)我需要,因为否则函数模板上的默认参数是VS2010中的错误.问题是它仍然无法编译.第一条消息是:error C2783: 'void foo(T)' : could not deduce template argument for '__formal' 即使我不想这样做,我也尝试通过调用它来明确说明我想要的模板

  foo<int, int>(10);
  foo<double, double>(10.1);
Run Code Online (Sandbox Code Playgroud)

但它仍然不起作用,新的错误是.

error C2975: 'foo' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression
Run Code Online (Sandbox Code Playgroud)

我希望有人可以告诉我如何解决这个问题,当然所有关于我的风格和我的代码可能具有的其他问题的评论都是受欢迎的.:)

额外的问题:有人知道为什么VS2010默认情况下不允许在函数模板上使用默认参数吗?

mfo*_*ini 11

问题是第二个模板参数std::enable_if默认为void.所以你做的事情与以下几点完全相同:

template <typename T, void = 0>
Run Code Online (Sandbox Code Playgroud)

这使得替换总是失败.您可以使用类型的非类型模板参数int,您可以为其指定默认值0:

template <typename T, typename std::enable_if< std::is_same<T, int>::value, int >::type = 0>
Run Code Online (Sandbox Code Playgroud)

对两个重载都做同样的事情,它会起作用.

在这里演示.


Ker*_* SB 5

默认值= 0对于类型没有意义.相反,您需要一个默认类型:

template <typename T, typename = typename std::enable_if<cnd>::type>
void foo(T) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

现在foo只有在第二个参数的默认类型存在时才参与重载解析,即仅当条件为真时才参与.

顺便提一下,在C++ 11中新引入了函数模板的可缺省模板参数.(他们以前只是被遗忘了.)

请注意,如果您想要多次重载,这会很麻烦,因为您不能拥有重复的,相同的模板签名.您可以为每个重载提供一组不同的虚拟模板参数,但这不能很好地扩展.这篇文章说明了使用可变参数模板包的更好解决方案(也可在此处获得).

  • 那不行.您将有2个完全相同的定义,因为默认模板参数不会影响函数的签名. (2认同)