C++ 将std::enable_if从参数移动到模板参数
我基本上是在尝试做与相同的事情,但我无法让我的代码进行编译 我有一个简单的第一个版本,它的参数中有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) {
#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;
}