【发布时间】:2014-12-28 17:46:32
【问题描述】:
我正在写一些东西来使用 SFINAE 在某些条件下不生成函数。当我直接使用元代码时,它按预期工作,但是当我通过另一个类间接使用代码时,它无法按预期工作。
我认为这是一个 VC++ 的东西,但看起来 g++ 也有这个,所以我想知道是否有某些原因 SFINAE 没有被应用于这个案例。
代码很简单。如果使用的类不是“集合类”的基类,则不要生成该函数。
#include <algorithm>
#include <type_traits>
#define USE_DIRECT 0
#define ENABLE 1
class A{};
class B{};
class C{};
class D{};
class collection1 : A, B, C {};
class collection2 : D {};
#if USE_DIRECT
template<typename X>
typename std::enable_if<std::is_base_of<X, collection1>::value, X>::type fn(X x)
{
return X();
}
# if ENABLE
template<typename X>
typename std::enable_if<std::is_base_of<X, collection2>::value, X>::type fn(X x)
{
return X();
}
# endif
#else // USE_DIRECT
template<typename X, typename COLLECTION>
struct enable_if_is_base_of
{
static const int value = std::is_base_of<X, COLLECTION>::value;
typedef typename std::enable_if<value, X>::type type;
};
template<typename X>
typename enable_if_is_base_of<X, collection1>::type fn(X x)
{
return X();
}
# if ENABLE
template<typename X>
typename enable_if_is_base_of<X, collection2>::type fn(X x)
{
return X();
}
# endif
#endif // USE_DIRECT
int main()
{
fn(A());
fn(B());
fn(C());
fn(D());
return 0;
}
如果我将 USE_DIRECT 设置为 1 并将 ENABLE 设置为 0,则编译失败,因为没有函数 fn 接受参数 D。将 ENABLE 设置为 1 将阻止该错误的发生。
但是,如果我将 USE_DIRECT 设置为 0 并将 ENABLE 设置为 0,它将失败并显示不同的错误消息,但对于相同的情况,没有采用参数 D 的 fn。但是,将 ENABLE 设置为 1 将导致所有 4 个函数调用都失败。
为方便起见,这里是在线编译器中的代码:http://goo.gl/CQcXHr
谁能解释这里发生了什么以及为什么?
这看起来可能与Alias templates used in SFINAE lead to a hard error有关,但也没有人回答。
作为参考,以下是 g++ 生成的错误:
main.cpp: In instantiation of 'struct enable_if_is_base_of<A, collection2>':
main.cpp:45:53: required by substitution of 'template<class X> typename enable_if_is_base_of<X, collection2>::type fn(X) [with X = A]'
main.cpp:54:8: required from here
main.cpp:34:82: error: no type named 'type' in 'struct std::enable_if<false, A>'
typedef typename std::enable_if<std::is_base_of<X, COLLECTION>::value, X>::type type;
^
main.cpp: In instantiation of 'struct enable_if_is_base_of<B, collection2>':
main.cpp:45:53: required by substitution of 'template<class X> typename enable_if_is_base_of<X, collection2>::type fn(X) [with X = B]'
main.cpp:55:8: required from here
main.cpp:34:82: error: no type named 'type' in 'struct std::enable_if<false, B>'
main.cpp: In instantiation of 'struct enable_if_is_base_of<C, collection2>':
main.cpp:45:53: required by substitution of 'template<class X> typename enable_if_is_base_of<X, collection2>::type fn(X) [with X = C]'
main.cpp:56:8: required from here
main.cpp:34:82: error: no type named 'type' in 'struct std::enable_if<false, C>'
main.cpp: In instantiation of 'struct enable_if_is_base_of<D, collection1>':
main.cpp:38:53: required by substitution of 'template<class X> typename enable_if_is_base_of<X, collection1>::type fn(X) [with X = D]'
main.cpp:57:8: required from here
main.cpp:34:82: error: no type named 'type' in 'struct std::enable_if<false, D>'
【问题讨论】:
-
呃,在你的间接情况下,顾名思义,错误不在直接上下文中,所以这是一个真正的错误......
标签: c++ c++11 templates sfinae enable-if