为 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()
应该说明它适用于 int
和 double
值,但是对于某些原因我的只适用于 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?
我正在修补一个已有 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()
应该说明它适用于 int
和 double
值,但是对于某些原因我的只适用于 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?