Ошибка компилятора `назначение несовместимого типа в операторе if` - PullRequest
3 голосов
/ 27 октября 2019

Компилятор продолжает присваивать несовместимые типы во время сборки.

Сообщение об ошибке:

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 Template как 'int'

Кто-нибудь знает, почему это происходит илиесли есть обходной путь.

Ответы [ 2 ]

5 голосов
/ 27 октября 2019

Кто-нибудь знает, почему это происходит или есть обходной путь?

Поскольку вы используете (нормальное) if-else, даже если выполняется только одно из условий, всеостальные ветви else будут инициированы во время компиляции.

  1. Решение - 1

    Если у вас есть доступ только к , SFINE (т.е. "Ошибка замены не являетсяМетод ошибки ") и перегрузка функций будут одним из способов. только включит (т.е. создаст экземпляр) правильный метод в соответствии с шаблоном класса T, в TypedUserProperty<T> создан экземпляр класса.

    #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. При этом можно создать единственную ветвь , которая верна во время компиляции. @ songyuanyao объяснил это в своем ответе.

5 голосов
/ 27 октября 2019

Проблема в том, что даже если вы укажете аргумент шаблона как int, эти else части должны быть созданы во время компиляции.

Вы можете применить Constexpr Если (начиная с C ++ 17).

Если значение равно true, то оператор-ложь отбрасывается (если присутствует), в противном случае оператор-истина отбрасывается.

например

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