for*_*818 4 c++ templates sfinae c++11
当定义某种类型时,我想选择一个模板的特殊化。
我仍然无法绕开SFINAE :(.。我可能已经接近或者可能已经完全离开了。我尝试了不同的方法,这是某种方法,我至少希望了解为什么它不起作用(is_complete基本上是从这里被盗):
#include <iostream>
#include <type_traits>
template <typename T, class = void>
struct is_complete : std::false_type {};
template <typename T>
struct is_complete<T,decltype(void(sizeof(T)))> : std::true_type {};
// this should be called if foo is not defined
void test() { std::cout << "test base\n"; }
// forward declare foo
struct foo;
// this should be called if foo is defined
template <typename T>
std::enable_if<is_complete<foo>::value,void> test() {
foo::bar();
}
// this is either defined or not
struct foo{
static void bar() { std::cout << "foo bar\n"; }
};
int main(){
test();
}
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.8(-std=c++11)我得到:
if_type_defined.cpp: In instantiation of ‘struct is_complete<foo>’:
if_type_defined.cpp:16:32: required from here
if_type_defined.cpp:8:42: error: invalid application of ‘sizeof’ to incomplete type ‘foo’
struct is_complete<T,decltype(void(sizeof(T)))> : std::true_type {};
^
if_type_defined.cpp:8:42: error: invalid application of ‘sizeof’ to incomplete type ‘foo’
if_type_defined.cpp: In function ‘std::enable_if<true, void> test()’:
if_type_defined.cpp:17:3: error: incomplete type ‘foo’ used in nested name specifier
foo::bar();
^
Run Code Online (Sandbox Code Playgroud)
我想我或多或少知道什么地方出了问题:foo不依赖T,因此不需要替代就可以得到,foo而且我得到了一个硬错误而不是非错误。接下来,我尝试使用辅助工具
template <typename T>
struct make_foo_dependent {
using type = foo;
};
Run Code Online (Sandbox Code Playgroud)
并尝试在enable_if而不是foo直接内部使用它。但是,这只是增加了更多错误,我没有在此处添加它,因为恐怕这也会朝错误的方向发展。
如何根据foo定义的内容选择要调用的函数?如果foo未定义,则使用的代码foo不应发出硬错误,而应被编译器忽略。
PS:关于SFINAE的事情已经发生了很多变化,我发现很难找到将其自身限制为C ++ 11的资源,在这些资源中,似乎比新标准要麻烦一些。
是的,正如您所说,您应该test根据template参数进行设置T;并更好地制作两个重载模板。例如
// this should be called if foo is not defined
template <typename T = foo>
typename std::enable_if<!is_complete<T>::value,void>::type test() { std::cout << "test base\n"; }
// this should be called if foo is defined
template <typename T = foo>
typename std::enable_if<is_complete<T>::value,void>::type test() {
T::bar();
}
Run Code Online (Sandbox Code Playgroud)
然后称它为
test(); // or test<foo>();
Run Code Online (Sandbox Code Playgroud)
顺便说一句:从您的意图来看,我认为的返回类型test应typename std::enable_if<is_complete<T>::value,void>::type为std::enable_if<is_complete<foo>::value,void>;这只是std::enable_if自身实例化的类型。
| 归档时间: |
|
| 查看次数: |
74 次 |
| 最近记录: |