[英]C++ templates: return value by type
我正在学习C ++和模板来实现一个配置文件阅读器( http://www.adp-gmbh.ch/cpp/chameleon.html ),我正在尝试为一个带有std::string
的类创建一个模板作为内部存储,在将其赋值给变量时可以返回其内部值(double,long double,float,string,uint16_t,uint32_t)。
平台: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;
};
使用时,我会执行以下操作:
uint32_t test = HybridType("50");
long double test2 = HybridType("50.0");
但是当我编译它时,我收到了很多警告:
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
我真的不明白为什么我有这些警告(编译器无法选择合适的类型),因为当我输出我的变量时,它们似乎有正确的值?
你的问题是operator T()
。 从编译器的角度来看它。 如果您展开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);
}
在编译器中,您可能会尝试从应该返回uint32_t
的函数返回long double。 当然,稍后在编译过程中,将优化到:
operator uint32_t() const {
return std::stoul(internalStr);
}
......但到那时,警告已经发出。
修复是:
formwerapproach的优势
模板在编译时进行评估,因此您不能使用if()
在运行时选择适当的转换函数(返回类型会发生冲突,因此会出现警告)。
您需要为您的强制转换运算符提供类型专用实现:
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. ...
Martin Booner的回答已经指出了核心问题。 我将为您想要在课堂上完成的内容提出一个更简单的解决方案。
仅当实现是通用的时,才能使用类和函数模板。 在你的情况下,这不是真的。 返回int
逻辑与返回double
逻辑不同。 使用成员函数模板不是模板的最佳用途。
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);
}
并不比任何简单:
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);
}
即使后者由于存在更多功能而更加冗长。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.