1

模板函数匹配不明原因的变化我有一个包含一个模板函数下面的代码。当我使用枚举的第二个参数调用此函数时:在某些情况下,它会查找模板特化,并且在某些情况下它不会。C++与枚举

我已经验证了枚举在两种情况下都是相同的枚举(例如没有重定义)并且其他参数具有正确的值,我发现一个编译是使用-Winline集合完成的(我没有尝试更改它)还有什么要看?

class A { 
public: 
    template <typename T> 
    int f(uint32_t id, T const& t, bool cond); 

    ... 
}; 

template <typename T> 
int A::f(uint32_t id, T const& t, bool cond) 
{ 
    ... 
} 

template <> 
inline int A::f<int>(uint32_t, int const& t, bool cond) 
{ 
    .... 
} 
+0

您允许其专业类外的函数模板而不在类中声明的专业化? – 2011-02-10 02:58:12

+0

@Jeremiah Willcock-是的,这是合法的。不过,您只能完全专注于此。我不知道为什么标准委员会决定合法。 – templatetypedef 2011-02-10 03:04:14

回答

2

对于初学者来说,通常使用模板专门化作为重载模板函数的方式是不可取的。模板特化与函数重载很难交互,并且有一些非常神秘的规则指定它们何时被选择,并且通常认为只提供常规函数重载比专用函数模板更好。

在这种情况下,我建议改变你的类是这样的:

class A { 
public: 
    template <typename T> 
     int f(uint32_t id, T const& t, bool cond); 
    int f(uint32_t id, int t, bool cond); 
    ... 
}; 

然后改变你的模板专业化仅仅是过载的实现。由于C++函数重载的方式,这将更准确地选择正确版本的函数。

至于你的问题,你的代码并不总是调用重载的原因是C++区分了枚举类型和类型int。虽然有int S和枚举类型之间进行转换的方式,他们是不一样的东西,并旨在捕捉int秒的过载,不能保证赶上枚举类型为好。你可能更适合重载函数来处理枚举的情况。

0

不是一个试图回答,但要发布超过将适合评论...

基本上,这表明预期的行为(枚举从未匹配INT专业化)的3.4.6 GCC。你使用什么编译器?你能提供一个类似的,完整的程序来产生错误吗?

#include <iostream>                

struct A                   
{                    
    public:                  
    template <typename T>              
    void f(const T&) { std::cout << "general\n"; }        
};                    

template <>                  
void A::f<int>(const int&) { std::cout << "specialised\n"; }      

enum E1 { Zero, One, Two };              

enum E2 { Max = INT_MAX };              

int main()                  
{                    
    A a;                   
    a.f("abc");                 
    a.f(123);                 
    a.f(Zero);                 
    E1 e = Two;                 
    a.f(e);                  
    a.f(Max);                 
} 

输出:

general 
specialised 
general 
general 
general