【问题标题】:Check C++ class publicly inherits from template class with anonymous parameter检查 C++ 类公开继承自具有匿名参数的模板类
【发布时间】:2016-03-01 03:31:23
【问题描述】:

类似于this question,如何在不指定模板参数的情况下测试Impl 类公开继承自模板类BaseTempl(即class Impl : public BaseTempl< ... >{ ... };)?

然而,与上述问题不同的是,如果继承不是公开的,我希望测试仍能编译(并返回 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’

【问题讨论】:

标签: c++ templates c++11 inheritance c++14


【解决方案1】:

以下基于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

【讨论】:

  • 如此接近我正在寻找的东西。我对这个 SFINAE 的东西真的很不好。有没有办法将 BaseTempl 抽象为 inherits_from_basetempl 类的参数?
  • Nvm。弄清楚了。接受您的回答,但添加我的修改版本以确保完整性。谢谢!
【解决方案2】:

通用答案:

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多