【发布时间】:2020-03-24 09:47:42
【问题描述】:
这个问题是另一个问题的后续问题:How to realize automatic type conversion for template methods?。
如果在模板方法中需要进行类型转换,我可以告诉编译器如何自己进行转换吗?
我知道编码转换的两种可能性:
- 模板专业化
- 提供转换重载(这是前一个问题的答案)。
两者都很好,但可能需要编写样板代码。有没有办法只“注入”类型转换代码,让编译器完成剩下的工作?
请参阅以下示例代码。我需要提供从std::string 到我的Setting 类的转换。我如何告诉编译器如何转换它?
#include <string>
#include <vector>
class Setting
{
public:
Setting(int)
{
}
Setting(double)
{
}
// It is not possible to provide a constructor taking std::string as argument,
// because this code is within an external libary!!!
};
// Is is not possible to create an overload of this method, since in real life
// it is a class member function within an external library.
//
void storeSetting(const Setting&)
{
// Storing setting...
}
// Template method that works with int, double and float, because Settings can
// be created from these basic types. But the method will not work
// for std::string, since there is no appropriate constructor.
template <typename Type>
void storeAll(std::vector<Type> elements)
{
// A lot of lengthy storage preparation code
// ...
//
// Final Storage
for (const Type& element : elements)
{
storeSetting(element);
}
}
// Solution by template specialization
template <>
void storeAll(std::vector<std::string> elements)
{
// A lot of lengthy storage preparation code
// ...
//
// Final Storage
for (const std::string& element : elements)
{
storeSetting(stoi(element));
}
}
// Solution by providing a conversion overload
//
// TODO: When containers are concerned, this is not handy.
// I dont have to repeat the "lengthy storage preparation code".
// On the other hand, the conversion code is lengthy boilerplate code itself.
// Is there another way to "inject" a user-defined type conversion?
void storeAll(std::vector<std::string> elements)
{
std::vector<int> convertedElements;
for (const std::string& element : elements)
{
convertedElements.push_back(stoi(element));
}
storeAll(convertedElements);
}
int main()
{
std::vector<double> numbers1 = {1.0, 2.0, 3.0};
std::vector<int> numbers2 = {2, 3, 4};
std::vector<float> numbers3 = {3.0, 4.0, 5.0};
storeAll(numbers1);
storeAll(numbers2);
storeAll(numbers3);
std::vector<std::string> numbers4 = {"4", "5", "6"};
storeAll(numbers4);
return 0;
}
【问题讨论】:
-
“编写样板代码”。大部分情况下都是正确的,因为您在错误的级别上做了:
void storeSetting(const std::string& s) { storeSetting(Setting(stoi(s))); }。甚至是makeSetting重载集。 -
@Jarod42 这是创建最小示例的缺点。 ;) 在我的实际代码中,
storeSetting的对应部分也是无法修改的第三方库的一部分(它是类成员函数)。我会修改我的问题... -
@Jarod42 当然,就原始示例代码而言,您的评论是完全正确的......我意识到我对可能的解决方案施加了许多限制。可能没有……有吗?
-
您始终可以将所有对
storeSetting的调用替换为对myStoreSetting的调用,并让您的包装器重载以处理转换。 -
风格问题,avoid specializing function templates。在这里可以进行专业化的事实只不过是对技术的好奇。对于现实世界的代码,您几乎肯定会想专门使用重载。
标签: c++ templates type-conversion