Compiler error `assigning incompatible type within if statement` [duplicate]

江枫思渺然 提交于 2021-01-03 06:28:15

问题


The compiler keeps assigning incompatible types during the build.

error Message:

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

Sample code

 /**
  * @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(); is the line the error occurs

"_value" is data type template T

in this case i'm setting the T Template as an 'int'

does anyone know why this is occuring or if theres a workaround.


回答1:


The problem is, even if you specify the template argument as int, those else parts have to be instantiated at compile-time.

You can apply Constexpr If (since C++17).

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

e.g.

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();
}



回答2:


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

Since you are using (normal) if-else, even if only one of the conditions is true, all the remaining else branches will be initiated at compile time.

  1. Solution - 1

    If you have access only to c++11, SFINE(i.e."Substitution Failure Is Not An Error") technique along with function overloading will be one way to go. That will only turn-on(i.e. instantiate) the correct method according to the class template T, in TypedUserProperty<T> class instantiation.

    #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. Solution - 2

    The above solution is more verbose, in c++17, as it provides the if constexpr feature. With this, one can instantiate the only branch which is true at compile time. @songyuanyao has explained this in his answer btw.



来源:https://stackoverflow.com/questions/58576826/compiler-error-assigning-incompatible-type-within-if-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!