2016-02-09 54 views
1

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

:-)嗨

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

#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 ; 
} 

,但我得到了以下错误消息从铛(G ++也给出了一个错误):

test_variadic.cpp:14:1: error: too many template parameters in template redeclaration template ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

而且还有我不明白。我虽然编译器会根据模板参数的数量选择类。由于第一个具有一个,另一个具有两个或更多个。

有什么想法?

非常感谢:-)

回答

1

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

+0

好的,这是有道理的,谢谢:-) – leo

2

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

至于获取可变参数模板做你想要的逻辑,它有助于从递归的角度来考虑它。下面的代码做你想要的:

#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; 
} 

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

+0

只需要注意,也会有一个运行时嵌套的“递归”式调用堆栈,并支付定期运行时递归的所有成本!作为回报f_()+ frest_(); frest_()将调用FSum operator()的嵌套调用,该调用将调用另一个FSum operator()的已分离版本等,直到它达到递归基础。我不知道编译器是否能够将此调用堆栈推广到操作符()评估的平坦序列。 – barney

+0

你对@barney。 “函数调用序列”的运行时间成本等于运行时递归。 –