条件使用声明

conditional using declaration

#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' 来解决问题,但它有一些成员,在那种情况下我会重复很多代码。有没有不同的,也许是棘手的方法?

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

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

Here 是完整示例。

您可以添加一个简单的转发重载,并在成员不存在于基class 时使用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 来延迟检查并使其在替换期间发生(当尝试调用函数时)而不是在 [= 时发生13=] 被实例化。

如果成员不存在,重载决策将丢弃新的重载(由于 ill-formed 替换),就好像它从未存在过一样。

但值得注意的是,这不适用于重载集(因为不能采用 pointer-to-member 的重载集)。它只有在你知道只有一个重载时才有效,它可以明确地形成 pointer-to-member。