假设我们有以下模板类
template<typename T> class Wrap { /* ... */ };
我们无法更改 Wrap
。这很重要。
让我们有来自Wrap<T>
的类。例如,
class NewInt : public Wrap<int> { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };
class Foo : public Wrap<Bar> { /* ... */ };
我们也无法改变这些类。以上所有课程均为第三方。他们不是我的。
我需要以下编译时间type_traits
:
template<class T>
struct is_derived_from_Wrap {
static const bool value = /* */;
};
我需要什么?
assert(is_derived_from_Wrap<Int>::value == true); // Indeed I need static assert
assert(is_derived_from_Wrap<MyClass>::value == true);
assert(is_derived_from_Wrap<char>::value == false);
struct X {};
assert(is_derived_from_Wrap<X>::value == false);
答案 0 :(得分:9)
你可以使用SFINAE做到这一点,但如果你不知道发生了什么,它会有点神奇......
template<typename T> class Wrap { };
struct myclass {};
struct X {};
class Int : public Wrap<int> { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };
template< typename X >
struct is_derived_from_Wrap
{
struct true_type { char _[1]; };
struct false_type { char _[2]; };
template< typename U >
static true_type test_sfinae( Wrap<U> * w);
static false_type test_sfinae( ... );
enum { value = sizeof( test_sfinae( (X*)(0) ) )==sizeof(true_type) };
};
#include <iostream>
#define test(X,Y) std::cout<<( #X " == " #Y )<<" : "<<( (X)?"true":"false") <<std::endl;
int main()
{
test(is_derived_from_Wrap <Int>::value, true);
test(is_derived_from_Wrap <MyClass>::value, true);
test(is_derived_from_Wrap <char>::value, false);
test(is_derived_from_Wrap <X>::value, false);
}
这给出了预期的输出
is_derived_from_Wrap <Int>::value == true : true
is_derived_from_Wrap <MyClass>::value == true : true
is_derived_from_Wrap <char>::value == false : false
is_derived_from_Wrap <X>::value == false : false
我的代码有几个问题。如果类型是Wrap,它也将返回true。
assert( is_derived_from_Wrap< Wrap<char> >::value == 1 );
如果需要,可以使用更多的SFINAE魔法来解决这个问题。
如果推导不是公共派生(即私有或受保护),它将返回false
struct Evil : private Wrap<T> { };
assert( is_derived_from_Wrap<Evil>::value == 0 );
我怀疑这无法修复。 (但我可能错了)。但我怀疑公共继承就足够了。
答案 1 :(得分:0)
以下确定是是否包装:
template<class T>
struct is_Wrap { static const bool value = false; };
template<typename T>
struct is_Wrap< Wrap<T> > { static const bool value = true; };
由于派生是一种Is-A关系,因此从Wrap<T>
派生的所有内容也都是Wrap<T>
,应该可以找到它。
答案 2 :(得分:0)
在一般情况下,你需要做一些相当复杂的模板元编程来确定一个类X是否来自另一个Y.基本上X来自Y if:
Andrei Alexandrescu在他的“现代C ++设计”一书中解释了如何做到这一点(以及许多其他模板技巧)。