问题
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.
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
, inTypedUserProperty<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(); } };
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