有条件的使用声明

时间:2019-05-19 08:38:47

标签: c++ metaprogramming generic-programming

#include <iostream>

using namespace std;

template<bool enable, typename T>
struct foo;

template<typename T>
struct foo<false , T>
{
    //nothing
};

template<typename T>
struct foo<true , T>
{
    void say_hello() 
    { 
        cout << "Hello !" << endl;
    }

    protected:

        int m_some_data_when_I_enabled{};
};

template<bool Enable, typename T>
struct bar
    :
    foo<Enable , T>
{
    //And there are lots of functions and members

    //Here I need conditional 'using'
    using foo<Enable , T>::say_hello;

    void say_hello(int different_signature)
    {

    }
};

struct duck {   };

int main(int, char**) {
    bar<true , duck> enabled_bar;
    bar<false , duck> disabled_bar;
}

当我声明bar时给出错误。对于我,这说得通。所以我需要类似的东西:

template<typename = typename std::enable_if<Enable>::type>
using foo<Enable , T>::say_hello();

我知道我可以解决“ bar”问题,但是它有一些成员,在这种情况下,我会重复很多代码。有其他不同的方法吗?

2 个答案:

答案 0 :(得分:3)

您可以在第一个foo中声明已删除的say_hello,从而使using中的bar语句合法。

template<typename T>
struct foo<false , T>
{
    void say_hello() = delete;
};

Here是完整的示例。

答案 1 :(得分:0)

您可以添加一个简单的转发过载,并在成员不存在于基类中时使用SFINAE有条件地禁用它。像这样:

template<typename V = T, typename = decltype(&foo<Enable, V>::say_hello)>
void say_hello() 
{ 
    bar::foo::say_hello();
}

See it Live

我们需要使用&foo<Enable, V>::say_hello而不是&foo<Enable, T>::say_hello来延迟检查并使其在替换期间(尝试调用该函数时)发生,而不是在{{1}时发生}实例化。

如果成员不存在,则重载解析将丢弃新的重载(由于格式不正确的替换),就好像它不存在一样。

但是值得注意的是,这不适用于过载集(因为不能将指针指向过载集的成员)。仅当您知道只有一个重载时,它才能工作,而重载可以明确地构成其成员指针。