当前位置: 首页 > 知识库问答 >
问题:

哪个编译器对模板方法专门化是正确的?

单于旭东
2023-03-14

考虑以下简单类:

template <class T>
class foo
{
   void set(int index, T value);
};

默认的模板化set方法对大多数T类型的值都很好,但我需要对特定类型的行为进行特殊化,将其称为String。

因此,在关联的CPP文件中,我添加了以下内容:

template <>
void foo<String>::set(int index,  String value)
{
   // code here
};
  1. 为什么在Xcode中工作而在Visual Studio中不工作
  2. 哪个编译器的行为正确,该问题应该被认为是另一个编译器中的bug吗?

顺便说一句,我尝试在头文件中创建一个显式签名:

template<>
void foo<String>::set(int index, String value );

Xcode对此没有抱怨,一切都仍然有效。然而,Visual Studio虽然没有抱怨头签名,但在链接时抱怨找不到匹配的实现,因此:

(public:void__cdecl foo >::print(int,class std::basic_string )“(?print@?$foo@v?$basic_string@du?$char_traits在函数主)

    Classes.h
    ---------
    #pragma once

    #include <iostream>
    #include <string>

    template <class T>
    class Foo
    {
       public:
          void print(int index, T value)
             {
                std::cout << "Using implicit template\n";
             }
    };




    Classes.cpp
    -----------

    #include "Classes.h"


    template<>
    void Foo<std::string>::print(int i, std::string xyz)
    {
       std::cout << "Using explicit String template\n";
    }



    Main.cpp
    --------

    #include <string>
    #include <iostream>

    #include "Sub/Classes.h"

    //==============================================================================
    int main (int argc, char* argv[])
    {

        Foo<double> f;
        
        f.print(1, 2.0);
        
        Foo<std::string> g;
        
        g.print(1, "abc");

        return 0;
    }

共有1个答案

曾洲
2023-03-14

您需要在.h文件中转发声明完整的专门化,以告诉其他翻译单元不要实例化通用模板。


template <typename T> struct foo {
  void set(int, T);
};

template <>
void foo<String>::set(int, String);

如果你不这样做,你就违反了一个定义规则。发生这种情况的原因是,当编译其他。cpp文件时,编译器不知道完全专门化的存在,而是实例化通用模板。

例如,在bar.cpp中,您编写foo ().set(1,{}); 。编译器根据通用模板的定义构造函数,并将其发送到.o.obj文件中。在链接时,链接器会看到foo ::set 的多个版本。它假设它们是等价的,并随机选择一个。你一般无法知道它会选择哪一个。更糟糕的是,对的某些调用可能是内联的,并且调用的版本可能与链接器选择的版本不同。这就是ODR违规行为如此危险的原因。

 类似资料:
  • 考虑以下头文件和源文件: 我在

  • 我有带转换操作符的简单代码,似乎所有的编译器都给出不同的结果,我很好奇哪个编译器是正确的?我也尝试了不同的组合,但以下是最有趣的。代码是使用C 11标志编译的,但是在C 03中也可能观察到相同的行为。 叮当声-3.6: g -4.9: msvc 2014年CTP: 删除后: msvc编译: 此外,在移除const in后 叮当声-3.6: g -4.9: msvc 2014年CTP:

  • 还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案

  • 对于DynamicMessage,我想使用不同的处理方式,所以我尝试了 但它给出了编译错误 com中的“addMessageToResult(Message,Descriptor,Builder)”。谷歌。云垂直方向。电信公司。taap。数据流。数据摄取。常见的解析器。CSVParserDynamicMessage与com中的addMessageToResult(Message,Descripto

  • 问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7