【问题标题】:Template template and partial specialization: a puzzle模板模板和偏特化:一个难题
【发布时间】:2016-03-10 16:53:46
【问题描述】:

考虑以下代码:

template<typename>
struct S { };

template<typename, typename>
struct B;

template <typename R, typename... Args, template<class> class C>
struct B<R(Args...), C<R>> {
    void f() { }
};

int main() {
    B<void(), S<void>> b;
    b.f();
}

它可以编译并且没有问题。
无论如何,当一个人决定使用B时,它必须提供两种类型。
我想要实现的是以某种方式默认第二个参数(我知道,部分专业化不接受其参数的默认值)并让用户将其类型定义为 B&lt;void()&gt; 而不是 B&lt;void(), S&lt;void&gt;&gt;
不幸的是,由于模板模板、部分特化和参数之间存在的依赖关系,它们共同导致了一个我在几个小时以来一直在努力解决的难题。

有什么聪明的解决办法吗?
到目前为止,我已经能够用中间结构解决它,但是我不太喜欢它......

【问题讨论】:

    标签: c++ templates c++11 template-specialization partial-specialization


    【解决方案1】:

    部分特化不接受默认参数,但主要特化接受。你可以在那里添加它:

    template<typename Sig, typename X = S<return_type_t<Sig>>>
    struct B;
    

    那么您需要做的就是为签名实现一个返回类型元函数。比如:

    template <class Sig>
    struct return_type;
    
    template <class Sig>
    using return_type_t = typename return_type<Sig>::type;
    
    template <class R, class... Args>
    struct return_type<R(Args...)> {
        using type = R;
    };
    

    【讨论】:

      【解决方案2】:

      您可以为此创建一个辅助类:

      template <typename T> struct default_arg;
      
      template <typename R, typename... Args>
      struct default_arg<R(Args...)>
      {
          using type = S<R>;
      };
      
      template<typename Sign, typename T = typename default_arg<Sign>::type>
      struct B;
      

      Demo

      【讨论】:

        【解决方案3】:

        这里我们把B改成模板别名。

        B_t 执行默认 arg 工作。

        B_implB 的实现,没有任何默认参数。

        B 是一个using 别名,得到B_t 的结果。

        template<class> struct S {};
        
        template<class, class>
        struct B_impl;
        
        template<class R, class... Args, template<class...> class C>
        struct B_impl<R(Args...), C<R>> {
          void f() { }
        };
        
        template<class, class=void>
        struct B_t;
        
        template<class R, class...Args>
        struct B_t<R(Args...), void>:
          B_t<R(Args...),S<R>>
        {};
        
        template<class R, class... Args, template<class...> class C>
        struct B_t<R(Args...), C<R>> {
          using type=B_impl<R(Args...), C<R>>;
        };
        
        template<class Sig, class Z=void>
        using B=typename B_t<Sig,Z>::type;
        

        缺点是B 上的模式匹配效果不佳。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多