为 std::to_string() 获取自己的补丁,以便在旧编译器上与双打一起正常工作

Getting a roll-your-own patch for std::to_string() to work properly with doubles on an old compiler

我正在修补一个已有 15-20 年历史且已有 10 年未维护的系统中的安全漏洞。因此,我的大多数 "patches" 都是真正的解决方法和问题,因为真正的解决方案会破坏工作(如果不安全)系统的完整性。我应用的 "patches" 之一与我的旧编译器 not being able to find to_string() within std 有关,它工作得很好,但并不完美。

在这数千行代码的某处,我尝试使用 patch::to_string() 转换 double,但编译失败并出现以下错误:

    g++  -o main -Wall -g -Wextra -pedantic main.o veracodefunctions.o
main.o: In function `main':
/home/(omited for privacy)/2_Test/main.cpp:8: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> > patch::to_string<double>(double const&)'
collect2: ld returned 1 exit status
*** Error code 1
clearmake: Error: Build script failed for "main"

下面是我使用的补丁的原始实现,我从 the above Stack Overflow post 获得,应该可以工作:

#include <string>
#include <sstream>

namespace patch
{
    template < typename T > std::string to_string( const T& n )
    {
        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;
    }
}

#include <iostream>

int main()
{
    std::cout << patch::to_string(1234) << '\n' << patch::to_string(1234.56) << '\n' ;
}

cMinor 的补丁在其底部有这个 main() 应该说明它适用于 intdouble 值,但是对于某些原因我的只适用于 int,而不适用于 double。这是我的实现:

patch.h:

8 #include <string>
...
25 namespace patch
26 {
27    template < typename T > std::string to_string( const T& n );
28 }

patch.cpp:

6 #include <string>
7 #include <sstream>
8 #include <stdexcept>
9 #include "patch.h"
...
41 namespace patch
42 {
43    template < typename T > std::string to_string( const T& n )
44    {
45       std::ostringstream stm;
46       stm << n;
47       return stm.str();
48    }
49 }

main.cpp:

2 #include <iostream>
3 #include "patch.h"
4 
5 int main () {
6 
7    std::cout << "\"12345\" to string is: " << patch::to_string(12345) << std::endl;
8    std::cout << "\"12.345\" to string is: " << patch::to_string(12.345) << std::endl;
9    return 0;
10 
11 }

这样你就不用滚动了,这里又是编译错误:

    g++  -o main -Wall -g -Wextra -pedantic main.o veracodefunctions.o
main.o: In function `main':
/home/(omited for privacy)/2_Test/main.cpp:8: undefined reference to `std::basic_string<char, std::char_traits<char>, std::allocator<char> > patch::to_string<double>(double const&)'
collect2: ld returned 1 exit status
*** Error code 1
clearmake: Error: Build script failed for "main"

任何见解将不胜感激!

您仅在 header 中声明 to_string(),并在 cpp 文件中定义。虽然这是 non-template 函数的正常方式,但对于模板来说这是不正确的。您需要将 definition(实际实现)放在 .h header 文件中,而不是放在 .cpp 文件中。

patch.h:

#include <string>
#include <sstream>
#include <stdexcept>

namespace patch
{

    template < typename T > std::string to_string( const T& n )
    {
       std::ostringstream stm;
       stm << n;
       return stm.str();
    }
}

当您实例化一个 header 类型时,编译器将为该实例创建一个新的 class。如果您的函数的实现不在 header 中,则在编译时将无法访问它,这就是您收到链接器错误的原因。

这个问题在这里得到了大部分回答: Why can templates only be implemented in the header file?