C++与枚举匹配的模板函数中无法解释的变化

发布于 2024-10-16 20:54:09 字数 492 浏览 7 评论 0原文

我有以下包含模板函数的代码。当我使用第二个参数作为枚举来调用此函数时:在某些情况下,它会找到模板专业化,而在某些情况下则不会。

我已经验证枚举在两种情况下都是相同的枚举(例如没有重新定义)并且其他参数具有正确的值,我发现一个编译是使用 -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)
{
   ....
}

I have the following code containing a template function. When I am calling this function with second parameter being an enum: in some cases it finds the template specialization and in some cases it does not.

I had verified that enums are the same enums in both cases (e.g there are no redefinitions) and that other parameters have correct values, I found that one compilation is done with -Winline set (I did not try changing it yet) what else to look at?

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)
{
   ....
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怀中猫帐中妖 2024-10-23 20:54:09

对于初学者来说,通常不建议使用模板专门化作为重载模板函数的方式。模板特化与函数重载的交互很差,并且有一些相当晦涩的规则来规定何时选择它们,并且通常认为仅提供常规函数重载比专门化函数模板更好。

在这种情况下,我建议将您的类更改为如下所示:

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 的重载并不能保证捕获枚举类型以及。您最好专门重载该函数来处理枚举的情况。

For starters, typically, it's inadvisable to use template specialization as a way of overloading a template function. Template specializations interact poorly with function overloading and have some pretty arcane rules dictating when they're chosen, and in general it's considered better to just provide a regular function overload than to specialize a function template.

In this case, I'd advise changing your class to look like this:

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);
    ...
};

Then changing your template specialization to just be an implementation of the overload. Due to the way that C++ function overloading works, this will select the correct version of the function more accurately.

As for your particular question, the reason that your code isn't always calling the overload is that C++ makes a distinction between an enumerated type and the type int. Though there are ways of converting between ints and enumerated types, they aren't the same thing, and an overload designed to catch ints is not guaranteed to catch enumerated types as well. You are probably better off specifically overloading the function to handle the enumerated case.

囚我心虐我身 2024-10-23 20:54:09

不是尝试的答案,但想要发布的内容超出了评论的范围...

基本上,这显示了 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

Not an attempted answer, but want to post more than will fit in a comment...

Basically, this shows expected behaviour (enums never matching int specialisation) for GCC 3.4.6. What compiler are you using? Can you actually provide a similar, complete program that produces the error?

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

Output:

general
specialised
general
general
general
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文