基于类成员的存在/不存在专门化C ++模板?

时间:2012-04-27 16:53:14

标签: c++ templates template-specialization typetraits

请考虑以下事项:

struct A {
  typedef int foo;
};

struct B {};

template<class T, bool has_foo = /* ??? */>
struct C {};

我想专门化C以使C&lt; A&gt;得到一个专业化和C&lt; B&gt;根据typename T :: foo的存在与否来获取另一个。这可能是使用类型特征还是其他一些模板魔法?

问题是我在尝试实例化C&lt; B&gt;时所尝试的一切都会产生编译错误。因为B :: foo不存在。但这就是我想要测试的东西!


编辑: 我认为ildjarn的答案更好,但我终于提出了以下C ++ 11解决方案。男人是hacky,但至少它很短。 :)

template<class T>
constexpr typename T::foo* has_foo(T*) {
  return (typename T::foo*) 1;
}
constexpr bool has_foo(...) {
  return false;
}
template<class T, bool has_foo = (bool) has_foo((T*)0)>

2 个答案:

答案 0 :(得分:6)

另一种(C ++ 03)方法:

template<typename T>
struct has_foo
{
private:
    typedef char no;
    struct yes { no m[2]; };

    static T* make();
    template<typename U>
    static yes check(U*, typename U::foo* = 0);
    static no check(...);

public:
    static bool const value = sizeof(check(make())) == sizeof(yes);
};

struct A
{
    typedef int foo;
};

struct B { };

template<typename T, bool HasFooB = has_foo<T>::value>
struct C
{
    // T has foo
};

template<typename T>
struct C<T, false>
{
    // T has no foo
};

答案 1 :(得分:2)

这样的事情可能有所帮助:has_member

typedef char (&no_tag)[1]; 
typedef char (&yes_tag)[2];

template< typename T > no_tag has_member_foo_helper(...);

template< typename T > yes_tag has_member_foo_helper(int, void (T::*)() = &T::foo);

template< typename T > struct has_member_foo {
    BOOST_STATIC_CONSTANT(bool
        , value = sizeof(has_member_foo_helper<T>(0)) == sizeof(yes_tag)
        ); }; 

template<class T, bool has_foo = has_member_foo<T>::value> 
struct C {};