0

以下代码在使用 Clang 的 macOS 上编译和运行正确,但在使用 MSVC 2017 的 Windows 上却没有。

// File: toString.h
#include <string>
template<typename T>
const std::string toString(T){return "";}

// File: toString.cpp
#include "toString.h"
template <>
const std::string toString<int>(int value){
    return std::to_string(value);
}

// File: main.cpp
#include <iostream>
#include "toString.h"

int main() {
    // specialized
    std::cout <<"int: "<< toString(1) << std::endl;
    // not specialized
    std::cout <<"double: "<< toString(1.0) << std::endl;
    return 0;
}

// Expected output:
// int: 1
// double: 

它在链接器处失败,因为函数是隐式实例化的,而不是链接到 int 特化,导致重复符号。

如果模板的默认实现被删除,那么打印的double行将失败,因为没有符号可以链接它。

我的问题是是否有任何方法可以在使用 MSVC 的 Windows 上实现相同的结果,而 main.cpp 没有任何 toString 专业化(声明或定义)的可见性。

如果没有,这是标准涵盖的还是仅仅是编译器实现细节?

4

1 回答 1

1

没有什么tostring.h可以告诉编译器您的专业化存在。因此,在编译时,编译main.cpp器只需实例化头文件中声明的模板。违反了一个定义规则,因此行为未定义。它在 clang 中按您期望的那样工作,主要是由于在链接时 clang 选择了您想要的两个可用定义的运气。

要修复它,您需要在标头中转发声明您的专业化,以便编译器知道在编译时不要实例化模板main.cpp

//toString.h
#include <string>
template<typename T>
const std::string toString( T ) { return ""; }

template <>
const std::string toString<int>( int value );
于 2019-01-15T14:46:51.357 回答