部分特化不使用其任何模板参数

时间:2018-03-16 19:41:17

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

我尝试使用模板元编程实现元组,但是我遇到了索引函数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<N,A...>是一个类型函数,它从A选择第N个索引处的类型。

2 个答案:

答案 0 :(得分:1)

也许您必须按照以下方式对get进行部分专业化

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

我的意思是...... get<0, R, A...>,而不是get<0>

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

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

否则,您还可以要求将类型管理设置为operator()的模板版本,并仅保留int N的{​​{1}}值

get

从C ++ 14开始,您可以避免使用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(); } }; 部分。

非主题建议:避免使用可能与decltype()命名空间名称冲突的名称。

可能stdmyGet而不是myTupleget

否则,您可以将所有内容放入个人命名空间(TuplemyNs::get

答案 1 :(得分:1)

您的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