我尝试使用std::enable_if
使用未使用和未命名的类型参数,以免扭曲return
类型。但是,以下代码无法编译。
#include <iostream>
template <typename T, typename = std::enable_if_t<!std::is_integral<T>::value>>
T foo() { std::cout << "non-integral" << std::endl; return T(); }
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
T foo() { std::cout << "integral" << std::endl; return T(); }
int main() {
foo<float>();
foo<int>();
}
编译器说:
7:3: error: redefinition of 'template<class T, class> T foo()'
4:3: note: 'template<class T, class> T foo()' previously declared here
In function 'int main()':
11:12: error: no matching function for call to 'foo()'
11:12: note: candidate is:
4:3: note: template<class T, class> T foo()
4:3: note: template argument deduction/substitution failed:
这里有什么问题?我必须如何更改代码才能编译? 《Discovering Modern C++》教科书明确鼓励使用std::enable_if
带有匿名类型参数。
编辑:我知道如果我放的话它会起作用std::enable_if
进入返回类型。然而,我的目的是获得更多细节,为什么如果我将它与匿名类型参数一起使用,它不起作用。正如我所说,我的教科书鼓励使用匿名类型参数的变体,所以我想知道为什么我的代码无法编译。
然而,我的目的是获得更多细节,为什么如果我将它与匿名类型参数一起使用,它不起作用。
默认值不参与重载解析,因此您实际上是在重新定义相同的函数。
让我们简化您的示例:
template<typename = int>
void f() {}
template<typename = void>
void f() {}
int main() {
f<>();
}
上面的代码无法编译,因为它不知道什么版本f
你想调用。
在你的情况下,如果我调用foo
as foo<void, void>
,我也有几乎同样的问题。
编译器无法猜测我的意图,并且第二个参数具有默认值这一事实并不意味着您不能传递不同的类型。
因此,代码格式不正确,编译器会正确地给出错误。
附带说明一下,您仍然可以在不使用std::enable_if_t
在返回类型中。
举个例子:
#include <type_traits>
#include <iostream>
template <typename T, std::enable_if_t<!std::is_integral<T>::value>* = nullptr>
T foo() { std::cout << "non-integral" << std::endl; return T(); }
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
T foo() { std::cout << "integral" << std::endl; return T(); }
int main() {
foo<float>();
foo<int>();
}
当我试图弄清楚OP的(错误)假设是什么并解释为什么会出现这种情况时,@T.C.正确地指出了对该答案的评论中实际原因的关注。
值得引用他的评论来为答案添加更多细节:
这不是重载解析;而是重载解析。这是声明匹配。首先,没有两个重载会产生任何歧义。这是两个重新定义错误:函数模板和默认模板参数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)