模板重新声明中的模板参数太多

时间:2016-02-09 02:44:46

标签: c++ templates clang variadic

嗨: - )

我有以下代码:目标是返回一个大致是其他函数之和的函数。并了解可变参数模板。

#include <iostream>

template <typename F>
struct FSum {
    FSum(F f) : f_(f) {} ;
    int operator()() {
        return f_() ;
    }
    F f_ ;
} ;
template <typename F1, typename F2, typename... Frest>
struct FSum {
    FSum(F1 f1, F2 f2, Frest... frest) {
        f_ = f1 ;
        frest_ = FSum<F2, Frest...>(f2, frest...) ;
    }
    int operator()() {
        return f_() + frest_() ;
    }
    F1 f_ ;
    FSum<F2, Frest...> frest_ ;
} ;

struct F1 {
    int operator() () { return 1 ; } ; 
} ;
struct F2 {
    int operator() () { return 2 ; } ; 
} ;
struct F3 {
    int operator() () { return 3 ; } ; 
} ;

int main() {
    F1 f1 ; 
    F2 f2 ;
    F3 f3 ;
    FSum<F1, F2, F3> fsum = FSum<F1, F2, F3>(f1, f2, f3) ;
    std::cout << fsum() << std::endl ;
}

但是我从clang得到了以下错误消息(g ++也给出了错误):

  

test_variadic.cpp:14:1:错误:模板参数太多了   模板         重新声明模板^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~

而且我不明白。我虽然编译器会根据模板参数的数量选择类?因为第一个只有一个而另一个有2个或更多。

有什么想法吗?

非常感谢: - )

2 个答案:

答案 0 :(得分:3)

编译器抱怨,因为您重新声明了两次相同的模板结构,而您需要的是部分模板专业化。请参阅以下示例中的语法。

至于让variadic模板做你想做的事情的逻辑,有助于从递归的角度来考虑它。以下代码可以满足您的需求:

#include <iostream>

using namespace std;

// stops "recursion" when it is called with no parameters
template <typename... Frest> struct FSum {
    int operator()() {
        return 0;
    }
};

// Partial Specialization of FSum above
// called when there is at least one template parameter
template <typename F, typename... Frest>
struct FSum<F, Frest...> {

    // "recursion" in the construction of frest_
    FSum(F f, Frest... frest) : f_(f), frest_(frest...) {}

    // "recursion" in the calling of frest()
    int operator()() {
        return f_() + frest_();
    }

    F f_;
    FSum<Frest...> frest_;
};


struct F1 {
    int operator()() { return 1; }
};

struct F2 {
    int operator()() { return 2; }
};

struct F3 {
    int operator()() { return 3; }
};

int main() {
    F1 f1;
    F2 f2;
    F3 f3;
    FSum<F1, F2, F3> fsum(f1, f2, f3);
    cout << fsum() << endl;
}

请注意,我使用“递归”一词,但据我所知,没有递归。相反,在编译时会生成一系列函数调用。

答案 1 :(得分:2)

您不能拥有2种具有不同模板参数的类型。您正在尝试将类用作函数(您可以在其中共享多个定义/名称),但类和结构不能以这种方式工作。您需要重命名其中一个结构或将它们合二为一。