c++ - 奇怪的g ++编译器行为在模板函数中键入id
问题描述
我尝试创建一些多态类成员模板函数来处理多种类型:
class MyClass
{
public:
template<typename T>
void AddType(T value);
private:
bool b_val;
int i_val;
std::string str_val;
}
template<typename T>
void MyClass::AddType(T value)
{
if(typeid(T) == typeid(bool))
{
b_val = value;
}
else if(typeid(T) == typeid(int))
{
i_val = value;
}
else if(typeid(T) == typeid(std::string))
{
str_val = val
}
}
用法:
MyClass message;
std::string s = "string";
int i = 123;
message.AddType(s);
message.AddType(i);
由于某种原因,我得到编译器错误:
error: assigning to 'bool' from incompatible type 'std::__cxx11::basic_string<char>'
b_val = value;
^~~~~
note: in instantiation of function template specialization 'MyClass::AddType<std::__cxx11::basic_string<char> >' requested here
message.AddType(s);
为什么编译器猜测 T 是 std::string?
更新:可重现的错误
解决方案
您的错误的原因是if
s 基本上是运行时构造,而模板是编译时构造。
这真正意味着,在编译之后,您的模板函数将如下所示:
void MyClass::AddType(std::string value)
{
if(some_value_for_typeid(std::string) == some_value_for_typeid(bool))
{
b_val = value;
}
else if(some_value_for_typeid(std::string) == some_value_for_typeid(int))
{
i_val = value;
}
}
让我们更清楚一点:
void MyClass::AddType(std::string value)
{
if(2 == 3)
{
b_val = value;
}
else if(2 == 5)
{
i_val = value;
}
}
标准 if需要能够运行它的主体,以防条件永远为真。所以,它被编译了,它失败了。
关于这个还能做什么?有多种选择。
最接近您的解决方案是使用新的 C++17 if constexpr
。此构造的行为与常规 完全相同if
,只是在编译时对其进行评估。缺点是表达式必须可以在编译时求值(它必须是一个constexpr
表达式),并且operator==
for std::type_info
(由 返回的东西typeid
)不是 constexpr。但是,有std::is_same
, 它以 constexpr 方式进行类型比较:
template<typename T>
void MyClass::AddType(T value)
{
if constexpr (std::is_same<T, bool>::value) {
b_val = value;
} else if constexpr (std::is_same<T, bool>::value) {
i_val = value;
}
}
编译它时,整个 if 构造将减少为要么b_val = value;
,i_val = value;
要么什么都没有。
MyClass::AddType(bool);
另一种选择是通过简单地定义和来简单地具有函数重载MyClass::AddType(int)
。
第三种方法是做一些模板专业化(我个人认为在这种特定情况下这不是一个好主意)。
推荐阅读
- r - 在单区混合模型中绘制多个随机效应
- android - 使用时区设置当前时间
- php - WordPress AJAX 多数据参数
- qgis - qgis - 创建层 - 看不到纬度值
- c# - ACR1252 NFC读写器序列号
- webrtc - webrtc mips build:为什么 rtc_executable build 生成 ELF 32 位 LSB 共享对象而不是 ELF 32 位 LSB 可执行文件
- ios - 如果 TextField 为空,则禁用按钮
- javascript - translate x 的计时精度不正确
- r - 如何从 sparklyr 的交叉验证器中获取最佳模型的特征重要性?
- html - Bootstrap:位置固定在模态内部的元素未相对于视口对齐