Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将std::enable_if从参数移动到模板参数_C++_Function Templates - Fatal编程技术网

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

C++ 将std::enable_if从参数移动到模板参数,c++,function-templates,C++,Function Templates,我基本上是在尝试做与相同的事情,但我无法让我的代码进行编译 我有一个简单的第一个版本,它的参数中有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::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;
}
但它仍然不起作用,新的错误是

error C2975: 'foo' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression
我希望有人能告诉我如何解决这个问题,当然欢迎大家对我的风格和我的代码可能存在的其他问题发表评论。:)


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

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

模板
void foo(T){/*…*/}
现在
foo
仅当第二个参数的默认类型存在时,即仅当条件为true时,才参与重载解析

顺便说一下,C++11中新引入了函数模板的可默认模板参数。(他们之前只是被遗忘了。)


请注意,如果您想要多个重载,这会变得很麻烦,因为您不能有重复的、相同的模板签名。您可以为每个重载提供一组不同的伪模板参数,但这不能很好地扩展。还说明了使用可变模板包的更好解决方案。

问题在于
std::enable\u中的第二个模板参数默认为
void
。因此,你所做的事情与:

template <typename T, void = 0>
对这两个重载执行相同的操作,它将起作用


演示。

如果在这种情况下,您可以只执行普通重载,而不是启用_:

#include <iostream>

void foo(int) {
  std::cout << "int" << std::endl;
}

template <typename T>
void foo(T) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}
#包括
void foo(int){

std::cout这行不通。您将有两个完全相同的定义,因为默认模板参数不会影响函数的签名。这将导致:错误C2995:'void foo(t)':函数模板已定义(如mfontanini所说)@mfontanini:你是对的。你必须给每个重载赋予不同的模板参数。按照RMF的建议做得更好。该死,我的VS2010仍然显示错误C2783:“void foo(T)“:无法推导出“\uu formal”的模板参数好吧,这就是方法。也许你应该更新你的编译器,或者切换到一个更符合标准的编译器。好吧,很高兴知道。我会尝试将其包装在类模板中,以使VS满意。因此,默认的非类型参数是明确的,但默认的类型参数不是很有趣。@Ke”rrek:嗯,可以说,这个答案中的“模板签名”是
,而在你的答案中总是
。我建议阅读。@下士-VS2010不会这样做。
template <typename T, typename = typename std::enable_if<cnd>::type>
void foo(T) { /* ... */ }
template <typename T, void = 0>
template <typename T, typename std::enable_if< std::is_same<T, int>::value, int >::type = 0>
#include <iostream>

void foo(int) {
  std::cout << "int" << std::endl;
}

template <typename T>
void foo(T) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}
#include <iostream>
#include <type_traits>

#define REQUIRES(...) ,class=typename std::enable_if<(__VA_ARGS__)>::type

void foo(int) {
  std::cout << "int" << std::endl;
}

template <typename T
  REQUIRES(!std::is_same<T,int>::value)
>
void foo(T) {
  std::cout << "not int" << std::endl;
}

int main(int argc, char* argv[])
{
  foo(10);
  foo(10.1);
  return 0;
}