编译器错误“在 if 语句中分配不兼容的类型”

Compiler error `assigning incompatible type within if statement`

编译器在构建过程中不断分配不兼容的类型。

错误信息:

error: assigning to 'int' from incompatible type 'QString'
typeduserproperty.cpp:115:28: note: in instantiation of member function 'core::TypedUserProperty<int>::setValue' requested here

示例代码

 /**
  * @brief setValue
  * set value to property
  * @param val
  * value to set to property
  * @return
  * true - successfully set value
  * false - invalid value
  */
template<class T>
void TypedUserProperty<T>::setValue(QVariant val)
{

   if (std::is_same<T, int>::value == true) 
   {
      this->_value = val.toInt();
   }
   else if (std::is_same<T, QString>::value == true)
   {
      this->_value = val.toString();
   }
   else if (std::is_same<T, double>::value == true)
   {
      this->_value = val.toDouble();
   }
}

this->_value = val.toString();是错误发生的行

“_value”是数据类型模板 T

在这种情况下,我将 T 模板设置为 'int'

有谁知道为什么会发生这种情况,或者是否有解决方法。

问题是,即使您将模板参数指定为 int,那些 else 部分也必须在编译时实例化。

您可以应用 Constexpr If(C++17 起)。

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

例如

if constexpr (std::is_same<T,int>::value == true) {
    this->_value = val.toInt();
} else if constexpr (std::is_same<T,QString>::value == true) {
    this->_value = val.toString();
} else if constexpr (std::is_same<T,double>::value == true){
    this->_value = val.toDouble();
}

Does anyone know why this is occurring or if there's a workaround?

由于您使用的是(正常)if-else,即使只有一个条件为真,所有剩余的else 分支也会在编译时启动。

  1. 解 - 1

    如果您只能访问 、SFINE(即 “替换失败不是 Error") 技术和函数重载将是一种方法。这将 仅打开(即实例化) 根据 [=43= 的正确方法] 模板 T,在 TypedUserProperty<T> class 实例化。

    #include <type_traits> // std::enable_if, std::is_same
    
    // helper traits for `std::enable_if`
    template<typename T, typename ReType = void> using EnableIfInteger = typename std::enable_if<std::is_same<T, int>::value, ReType>::type;
    template<typename T, typename ReType = void> using EnableIfDouble = typename std::enable_if<std::is_same<T, double>::value, ReType>::type;
    template<typename T, typename ReType = void> using EnableIfQString = typename std::enable_if<std::is_same<T, QString>::value, ReType>::type;
    
    template<class T> class TypedUserProperty
    {
       T _value;
    public:
       template<typename Type = T> // this will be instantiated when T = int
       auto setValue(QVariant val)->EnableIfInteger<Type> {
           this->_value = val.toInt();
       }
    
       template<typename Type = T> // this will be instantiated when T = double
       auto setValue(QVariant val)->EnableIfDouble<Type> {
           this->_value = val.toDouble();
       }
    
       template<typename Type = T> // this will be instantiated when T = QString
       auto setValue(QVariant val)->EnableIfQString<Type> {
           this->_value = val.toString();
       }
    };
    
  2. 解 - 2

    上面的解决方案在 中更为冗长,因为它提供了 if constexpr 特征。有了这个,就可以 实例化唯一的分支 这是 在编译时为真。 顺便说一句,他在回答中解释了这一点。