我有以下代码包含模板函数。当我调用这个函数时,第二个参数是枚举:在某些情况下,它会找到模板特化,在某些情况下它不会。
我已经验证了枚举在两种情况下是相同的枚举(例如,没有重新定义),并且其他参数具有正确的值,我发现一个编译是使用-Winline set完成的(我没有尝试更改它)还有什么可看的?
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 :(得分: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
和枚举类型之间进行转换,但它们不是同一个东西,并且设计用于捕获int
的重载也不能保证捕获枚举类型。你最好专门重载函数来处理枚举的情况。
答案 1 :(得分:0)
不是一个尝试过的答案,但希望发布超过评论的内容...
基本上,这显示了GCC 3.4.6的预期行为(枚举永远不会匹配int专业化)。你用的是什么编译器?你真的可以提供一个产生错误的类似的完整程序吗?
#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