2011-09-17 140 views
3

我有一个接受操作符对象作为参数的函数。这个操作符有点像回调。这个操作符对象的类型是一个模板参数。我怎样才能为它指定一个默认参数?模板函数的默认参数

#include <iostream> 

template<class IT, class NT> 
class A 
{ 
    public: 
    class DefaultHandler 
    { 
    public: 
     NT foo() { return NT(); } 
    }; 

    template <class HANDLER> 
    void action(HANDLER h = DefaultHandler()) // This default parameter is accepted by the compiler but appears to have no effect 
    { 
     std::cout << h.foo() << std::endl; 
    } 
}; 

int main() 
{ 
    A<int, double> a; 
    // I want this to be legal: 
    a.action(); // error: no matching function for call to ‘A<int, double>::action()’ 

    //a.action(A<int, double>::DefaultHandler()); // Works 
    return 0; 
} 
+1

不幸的是,C++ 03 14.8.2.4/17说: '模板类型参数不能从函数默认参数的类型“。 因此需要一些解决方法,如_iammilind_的答案。 –

+0

@Ise紫藤,完全回答我的问题,并以答案的形式表达,我会接受它。 – Adam

+0

真的吗?谢谢,我会尝试! –

回答

0

不幸的是,C++ 03 14.8.2.4/17说:

模板类型参数不能从 功能默认参数的类型推断

和举例如下:

template <class T> void f(T = 5, T = 7); 
void g() 
{ 
    f(1);     // OK: call f<int>(1,7) 
    f();     // error: cannot deduce T 
    f<int>();    // OK: call f<int>(5,7) 
} 

因为N3290 14.8.2。5/19也说明了相同的规范, 这似乎在新标准中没有改变...

2

模板函数的默认参数在C++ 03中是不允许的,但在C++ 11中是允许的。


参考文献:

C++ 03标准:14.1.9:

默认模板取值=之后指定一个模板参数(14.3)一个模板参数。可以为任何类型的模板参数(类型,非类型,模板)指定Adefault模板参数。可以在类模板声明或类模板定义中指定默认模板参数。 默认的模板参数不能在函数模板声明或函数模板定义中指定,也不能在类模板成员的定义的模板参数列表中指定。不应在朋友模板声明中指定默认的模板参数。

C++ 11:14.1.9:

默认模板参数是一个模板参数(14.3)在模板参数=之后SPECI音响编辑。可以为不是模板参数包(14.5.3)的任何类型的模板参数(类型,非类型,模板)指定一个默认模板参数。默认的模板参数可以在模板解析中指定。 默认的模板参数不应该在模板参数列表中指定出现在成员类之外的类模板成员的定义中。不应在朋友类模板声明中指定默认的模板参数 。如果朋友函数模板声明指定了默认的模板参数,那么该声明应该是一个定义,并且应该是翻译单元中函数模板的唯一声明。

+0

你知道他们是否被允许在C++ 11中吗? – Adam

+0

我刚刚看到你的编辑,这似乎并不适用于我的情况。我不想为模板参数指定默认值,我想为常规参数指定默认值,其类型恰好是模板化的。 您的报价适用于我想说'template ' – Adam

+0

的情况,但这并不回答这个问题。该代码具有默认的函数模板函数参数。它在C++ 03和C++ 11中均有效。问题是,为什么它不起作用? –

3

说了当前标准中不允许template的默认参数。下面是一个简单的解决办法来解决问题:

template <class HANDLER> 
void action(HANDLER h) { 
    std::cout << h.foo() << std::endl; 
} 
void action() { // wrapper 
    action(DefaultHandler()); // call the desired funciton 
} 

提供的包装,这使得默认参数为action()效果。 Demo