【问题标题】:Partial specialization does not use any of its template parameters部分专业化不使用其任何模板参数
【发布时间】:2018-08-25 23:19:01
【问题描述】:

我正在尝试使用模板元编程实现元组,但在索引函数get 上遇到问题。 Tuple 类型的实现是这样的:

template<typename A, typename... B>
class Tuple : Tuple<B...> {
    private:
        A val;
    public:
        using Base = Tuple<B...>;
        Base* base() {
            return static_cast<Base*>(this);
        }
        const Base* base() const {
            return static_cast<const Base*>(this);
        }
        Tuple(A a, B... b): Base(b...), val(a) { }
        A first() {
            return val;
        }
};

template<class A>
class Tuple<A> {
    private:
        A val;
    public:
        Tuple(A a): val{a} {}
        A first() {
            return val;
        }
};

get结构的实现是:

template<int N, class... A>
struct get {
    select<N,A...> operator()(Tuple<A...> t) {
        return get<N-1>()(t.base());
    }
};

template<class R, class... A>
struct get<0> {
    R operator()(Tuple<R, A...> t) {
        return t.first();
    }
};

这是编译器给我的错误:

tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
       ^
1 error generated.

为什么会出现此错误?我该如何纠正?

注意:select&lt;N,A...&gt; 是一个类型函数,它从A 中选择第 N 个索引处的类型。

【问题讨论】:

  • 我认为只要将template &lt;class R, class ... A&gt; 更改为template &lt;&gt; 并将Tuple&lt;R, A...&gt; 更改为Tuple&lt;0&gt; 即可解决。

标签: c++ c++11 variadic-templates template-meta-programming template-specialization


【解决方案1】:

也许您必须对get 进行部分专业化,如下所示

template<class R, class... A>
struct get<0, R, A...> {
    R operator()(Tuple<R, A...> t) {
        return t.first();
    }
};

我的意思是...get&lt;0, R, A...&gt;,而不是get&lt;0&gt;

但您还必须修改主 get 以使用正确的类型列表调用以下调用,所以

template<int N, typename A0, typename ... As>
struct get {
    auto operator()(Tuple<A0, As...> t) {
        return get<N-1, As...>()(t.base());
    }
};

否则,您还可以要求对operator() 的模板版本进行类型管理,并仅维护get 的int N 值

template <int N>
struct get
 {
   template <typename Tpl>
   auto operator() (Tpl t)
      -> decltype( get<N-1>()(t.base()) )
    { return get<N-1>()(t.base()); }
 };

template<>
struct get<0>
 {
   template <typename Tpl>
   auto operator() (Tpl t)
      -> decltype ( t.first() )
    { return t.first(); }
 };

从 C++14 开始,您可以避免使用 decltype() 部分。

离题建议:避免使用可能与std 命名空间名称冲突的名称。

也许是myGet 和myTuple 而不是get 和Tuple。

否则,您可以将所有内容放在个人命名空间中(例如 myNs::get 和 myNs::Tuple。

【讨论】:

    【解决方案2】:

    您的get 的主要模板是:

    template<int N, class... A>
    struct get{ ... };
    

    您的get 的部分专业是:

    template<class R, class... A>
    struct get<0>{ ... };
    

    专业化接收单个模板参数,即:0,但上面的主模板采用两个模板参数:

    • 非类型模板参数N。
    • 可变参数类型参数A。

    另外,R怎么推导出来?


    将get 特化为:

    template<class R, class... A>
    struct get<0, R, A...>{ ... };
    

    将使R 被推导成为可能:它将被推导为传递的可变参数的第一个元素的类型。例如,在:

    get<0, int, float, double> foo;
    

    R 将推导出为int。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多