2016-03-01 68 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; 
}