2016-03-01 63 views
4

this question类似,我如何测试类Impl是否从模板类BaseTempl(即class Impl : public BaseTempl<...>{ ... };)(没有指定模板参数)公开继承?检查C++类是否从模板类公开继承匿名参数

但是,与上述问题不同,如果继承不公开,我希望测试仍然能够编译(并返回false)。

理想情况下,代码会允许我做这样的事情:

class alpha : public BaseTempl<int>{}; 

class bravo : BaseTempl<int>{}; 

class charlie{}; 

class delta : public BaseTempl<int>, public charlie {}; 

class echo : public delta {}; 

int main(){ 
    publicly_inherits_from < alpha, BaseTempl >(); // true 
    publicly_inherits_from < bravo, BaseTempl >(); // false 
    publicly_inherits_from < charlie, BaseTempl >(); // false 
    publicly_inherits_from < delta, BaseTempl >(); // true 
    publicly_inherits_from < echo, BaseTempl >(); // true 
} 

从链接的问题的答案提供了以下错误,当我试图编译上面的代码:

error: ‘BaseTempl<int>’ is an inaccessible base of ‘bravo’ 
+0

的可能的复制[性状检查模板类的某些特化是否是特定类的基类](http://stackoverflow.com/questions/25845536/trait-to-check-if-some-specialization-of-template-class-is-base-类OF-特别) – Orient

回答

5

以下SFINAE为基础的方法似乎产生预期的结果。作为一个额外的好处,在BaseTempl模板可以采取可变参数的参数,而不仅仅是一个参数:

#include <iostream> 

template<typename ...Args> class BaseTempl {}; 

template<typename T> class inherits_from_basetempl { 

public: 

    template<typename ...Args> 
    static const bool sfinae_param(const BaseTempl<Args...> &a); 

    template<typename V=T> 
    static constexpr auto is_inherits(int) 
     -> decltype(sfinae_param(std::declval<V &>())) 
    { 
     return true; 
    } 

    static constexpr bool is_inherits(...) 
    { 
     return false; 
    } 

    static const bool value=is_inherits(0); 
}; 

class alpha : public BaseTempl<int>{}; 

class bravo : BaseTempl<int>{}; 

class charlie{}; 

class delta : public BaseTempl<int>, public charlie {}; 

class echo : public delta {}; 

int main() 
{ 
    std::cout << inherits_from_basetempl<alpha>::value << std::endl; 
    std::cout << inherits_from_basetempl<bravo>::value << std::endl; 
    std::cout << inherits_from_basetempl<charlie>::value << std::endl; 
    std::cout << inherits_from_basetempl<delta>::value << std::endl; 
    std::cout << inherits_from_basetempl<echo>::value << std::endl; 
} 

结果:

$ gcc --version 
gcc (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2) 
Copyright (C) 2015 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ g++ -std=c++14 -o t t.C 2>&1 | less 
$ ./t 
1 
0 
0 
1 
1 
+0

非常接近我正在寻找的东西。我对这个SFINAE的东西很不好。有没有办法将BaseTempl抽象为inherits_from_basetempl类的参数? –

+0

Nvm。弄清楚了。接受你的答案,但添加我的修改版本的完整性。谢谢! –

1

通用答案:

#include <iostream> 

template< typename ...Args > class BaseTempl {}; 

template< typename T, template<typename...> class B > 
class inherits_from_templ_base { 

    template< typename ... Args > static const bool sfinae_param(const B<Args...> &a); 

    template< typename V = T > 
    static constexpr decltype(sfinae_param(std::declval< V& >())) 
    inherits(int) { return true; } 

    static constexpr bool inherits(...) { return false; } 

    public: 

    static constexpr bool value = inherits(0); 
}; 

class alpha : public BaseTempl< int, char, long >{}; 

class bravo : BaseTempl< int, char >{}; 

class charlie{}; 

class delta : public BaseTempl<int>, public charlie {}; 

class echo : public delta {}; 

int main() 
{ 
    std::cout << inherits_from_templ_base<alpha,BaseTempl>::value << std::endl; 
    std::cout << inherits_from_templ_base<bravo,BaseTempl>::value << std::endl; 
    std::cout << inherits_from_templ_base<charlie,BaseTempl>::value << std::endl; 
    std::cout << inherits_from_templ_base<delta,BaseTempl>::value << std::endl; 
    std::cout << inherits_from_templ_base<echo,BaseTempl>::value << std::endl; 
}