[英]C++ templates: return value by type
I'm learning C++ and templates to implement a configuration file reader ( http://www.adp-gmbh.ch/cpp/chameleon.html ) and I'm trying to make a template for a class with a std::string
as internal storage, which can return its internal value when assigning it to a variable (double, long double, float, string, uint16_t, uint32_t). 我正在学习C ++和模板来实现一个配置文件阅读器( http://www.adp-gmbh.ch/cpp/chameleon.html ),我正在尝试为一个带有
std::string
的类创建一个模板作为内部存储,在将其赋值给变量时可以返回其内部值(double,long double,float,string,uint16_t,uint32_t)。
Platform: Win10 with Visual Studio Community 2015 Update 1 平台:Win10与Visual Studio社区2015 Update 1
class HybridType {
public:
HybridType() {};
explicit HybridType(const std::string& value) : internalStr(value) {}
explicit HybridType(const char* value) : internalStr (std::string(value)) { }
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
explicit HybridType(T numericValue) {
std::stringstream strstr;
strstr << std::setprecision(std::numeric_limits<T>::digits10 + 1) << numericValue;
internalStr = strstr.str();
}
operator std::string() const { return internalStr; }
template<typename T>
operator T() const {
if (std::is_same<T, std::uint16_t>::value) return std::stoi(internalStr);
if (std::is_same<T, std::uint32_t>::value) return std::stoul(internalStr);
if (std::is_same<T, std::uint64_t>::value) return std::stoul(internalStr);
if (std::is_same<T, double>::value) return std::stod(internalStr);
if (std::is_same<T, long double>::value) return std::stold(internalStr);
if (std::is_same<T, float>::value) return std::stof(internalStr);
return std::stoll(internalStr);
}
template<typename T> operator T*() { return internalStr.c_str(); }
private:
std::string internalStr;
};
When using it, I do the following: 使用时,我会执行以下操作:
uint32_t test = HybridType("50");
long double test2 = HybridType("50.0");
But when I compile this, I get a lot of warnings: 但是当我编译它时,我收到了很多警告:
1> warning C4244: 'return': conversion from 'double' to 'uint32_t',
possible loss of data 1> see reference to function template
instantiation 'HybridType::operator T(void) const<uint32_t>' being
compiled 1> with 1> [ 1> T=uint32_t 1> ]
1> warning C4244: 'return': conversion from 'long double' to
'uint32_t', possible loss of data 1> warning C4244: 'return':
conversion from 'float' to 'uint32_t', possible loss of data 1>
warning C4244: 'return': conversion from '__int64' to 'uint32_t',
possible loss of data
I didn't really understand why I have these warnings (compiler cannot choose the appropriate type), because when I output my variables they seem to have the correct value? 我真的不明白为什么我有这些警告(编译器无法选择合适的类型),因为当我输出我的变量时,它们似乎有正确的值?
Your problem is operator T()
. 你的问题是
operator T()
。 Look at it from the compiler's point of view. 从编译器的角度来看它。 If you expand for
uint32_t
you get: 如果您展开
uint32_t
您会得到:
operator uint32_t() const {
if (...) return std::stoi(internalStr);
if (...) return std::stoul(internalStr);
if (...) return std::stoul(internalStr);
if (...) return std::stod(internalStr);
if (...) return std::stold(internalStr); // Consider here
if (...) return std::stof(internalStr);
return std::stoll(internalStr);
}
Which looks to the compiler that you might be trying to return a long double from a function that is supposed to return uint32_t
. 在编译器中,您可能会尝试从应该返回
uint32_t
的函数返回long double。 Of course, later on in the compilation process, that will get optimized down to: 当然,稍后在编译过程中,将优化到:
operator uint32_t() const {
return std::stoul(internalStr);
}
... but by that time, the warning has been issued. ......但到那时,警告已经发出。
The fix is either: 修复是:
The advantage of the formwerapproach formwerapproach的优势
Templates are evaluated at compile time, thus you can't use if()
to select the appropriate conversion function at runtime (return types will conflict, hence the warnings). 模板在编译时进行评估,因此您不能使用
if()
在运行时选择适当的转换函数(返回类型会发生冲突,因此会出现警告)。
You need to provide type specialized implementations for your cast operator instead: 您需要为您的强制转换运算符提供类型专用实现:
class HybridType {
public:
// ...
template<typename T>
operator T() const {
static_assert(std::is_same<T, std::uint16_t>::value ||
std::is_same<T, std::uint32_t>::value
// ...
,"Casted to an unsupported type!");
}
// ...
};
template<>
HybridType::operator std::uint16_t() const {
return std::stoi(internalStr);
}
template<>
HybridType::operator std::uint32_t() const {
return std::stoul(internalStr);
}
// aso. ...
The answer by Martin Booner has already pointed out the core issue. Martin Booner的回答已经指出了核心问题。 I am going to suggest a simpler solution for what you want to accomplish in your class.
我将为您想要在课堂上完成的内容提出一个更简单的解决方案。
Using templates for classes and functions is worthwhile only when the implementation is generic. 仅当实现是通用的时,才能使用类和函数模板。 That's not true in your case.
在你的情况下,这不是真的。 The logic to return a
int
is different that logic to return a double
. 返回
int
逻辑与返回double
逻辑不同。 Using a member function template for this is not the best use of templates. 使用成员函数模板不是模板的最佳用途。
template<typename T>
operator T() const {
if (std::is_same<T, std::uint16_t>::value) return std::stoi(internalStr);
if (std::is_same<T, std::uint32_t>::value) return std::stoul(internalStr);
if (std::is_same<T, std::uint64_t>::value) return std::stoul(internalStr);
if (std::is_same<T, double>::value) return std::stod(internalStr);
if (std::is_same<T, long double>::value) return std::stold(internalStr);
if (std::is_same<T, float>::value) return std::stof(internalStr);
return std::stoll(internalStr);
}
is not any simpler than: 并不比任何简单:
operator std::uint16_t() const {
return std::stoi(internalStr);
}
operator std::uint32_t() const {
return std::stoul(internalStr);
}
operator std::uint64_t() const {
return std::stoul(internalStr);
}
operator double() const {
return std::stod(internalStr);
}
operator long double() const {
return std::stold(internalStr);
}
operator float() const {
return std::stof(internalStr);
}
operator long long() const {
return std::stoll(internalStr);
}
even though the latter is more verbose due the presence of more functions. 即使后者由于存在更多功能而更加冗长。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.