繁体   English   中英

SFINAE检测是否定义了类型

[英]SFINAE detect if type is defined

我想在定义某个类型时选择模板的特化。

我仍然无法围绕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();
}

使用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();
   ^

我想我或多或少知道错误: foo不依赖于T ,因此不需要替换来获取foo并且我得到一个硬错误而不是Not An Error。 接下来我试着沿着这条线使用一个帮手

template <typename T>
struct make_foo_dependent { 
   using type = foo;
};

并尝试直接在enable_if而不是foo使用它。 然而,这只是增加了更多错误,我没有把它包含在这里,因为我担心这也是错误的方向。

如何根据是否定义了foo来选择要调用的函数? 如果未定义foo ,则使用foo的代码不应发出硬错误,而是由编译器忽略。

PS:关于SFINAE的情况已经发生了很大变化,我发现很难找到限制自己使用C ++ 11的资源,在这些情况下,事情似乎比新标准更加毛茸茸。

是的,正如您所说,您应该根据模板参数T进行test ; 并且更好地制作两个重载模板。 例如

// 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();
}

然后称之为

test(); // or test<foo>();

LIVE(foo已定义)
LIVE(foo未定义)

BTW:从你的意图来看,我认为test的返回类型应该是typename std::enable_if<is_complete<T>::value,void>::type而不是std::enable_if<is_complete<foo>::value,void> ; 这只是std::enable_if本身的实例化类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM