【问题标题】:conditional using declaration有条件的使用声明
【发布时间】:2019-05-19 08:38:46
【问题描述】:
#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' 来解决问题,但它有一些成员,在这种情况下我会复制很多代码。有没有不同的,也许是棘手的方式?

【问题讨论】:

    标签: c++ metaprogramming generic-programming


    【解决方案1】:

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

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

    Here 是完整的示例。

    【讨论】:

      【解决方案2】:

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

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

      See it Live

      我们需要使用&amp;foo&lt;Enable, V&gt;::say_hello 而不是&amp;foo&lt;Enable, T&gt;::say_hello 来延迟检查并使其在替换期间发生(当尝试调用函数时),而不是在实例化bar 时发生。

      如果该成员不存在,重载决议将丢弃新的重载(由于格式错误的替换),就好像它从未存在过一样。

      但值得注意的是,这不适用于重载集(因为不能获取指向重载集成员的指针)。只有当你知道只有一个重载时它才会起作用,它可以明确地形成其指向成员的指针。

      【讨论】:

        猜你喜欢
        • 2014-07-29
        • 2021-08-02
        • 1970-01-01
        • 2011-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-04
        • 1970-01-01
        相关资源
        最近更新 更多