如果我在这里有DATA_T = std::string,我不能编译这段代码,因为错误"没有匹配的函数来调用'to_string'"。该函数不允许将字符串转换为字符串。但我需要得到字符串无论如何,我怎么能解决这个错误和编译程序?
template <typename DATA_T>
std::string get_string(DATA_T subdata) {
std::string data = "...";
if (typeid(subdata) == typeid(std::string))
data += subdata;
else
data += std::to_string(subdata);
return data;
}
在c++ 17中,使用if constexpr
:
#include <string>
#include <type_traits>
template <typename DATA_T>
std::string get_string(DATA_T subdata) {
std::string data = "...";
if constexpr (std::is_same_v<DATA_T, std::string>)
data += subdata;
else
data += std::to_string(subdata);
return data;
}
参见c++ 17之前的解决方案的另一个答案。
与其在函数体中分支模板实参的类型,不如编写一个重载,当实参是std::string
时优先使用。
template <typename DATA_T>
std::string get_string(DATA_T subdata) {
std::string data = "...";
data += std::to_string(subdata);
return data;
}
std::string get_string(std::string subdata)
{
std::string data = "...";
data += subdata;
return data;
}
如其他答案所示,可以为std::string
添加一个特例。这将解决您的std::string
问题,但其他类型如何?
当我第一次看到to_string
时,我很失望,因为它只有有限的重载集。然而,我误解了to_string
是什么意思。它意味着将转换为字符串,就像std::sprintf
使用正确的格式说明符所做的那样。由于sprintf
继承自C语言,它不能将c++中可以转换为字符串的所有类型转换为字符串。没有办法通过sprintf
直接启用自定义类型的转换。正因为如此,to_string
也有同样的限制。特别是没有to_string(const std::string&)
。
重载std::ostream& operator<<(std::ostream&,const T&)
更灵活。你想用foo
还是bar
来调用get_string
?为什么不:
#include <iostream>
#include <sstream>
template <typename DATA_T>
std::string get_string(DATA_T subdata) {
std::stringstream data;
data << "...";
data << subdata;
return data.str();
}
struct foo {};
std::ostream& operator<<(std::ostream& out,const foo& f){
return out << "foo";
}
int main() {
foo f;
std::cout << get_string(f);
}
如果你真的想像sprintf
那样转换,我可能会继续使用其他答案中提出的解决方案之一。