编译器错误`在if语句中分配不兼容的类型`[重复]

Posted

技术标签:

【中文标题】编译器错误`在if语句中分配不兼容的类型`[重复]【英文标题】:Compiler error `assigning incompatible type within if statement` [duplicate] 【发布时间】:2019-10-27 05:18:21 【问题描述】:

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

错误信息:

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-&gt;_value = val.toString(); 是发生错误的行

“_value”是数据类型模板T

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

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

【问题讨论】:

'编译器不断分配不兼容的类型'。不会。编译器会不断打印编译错误关于分配不兼容的类型。 编译器不做这样的事情。您编写了该代码,而不是编译器:)。该错误告诉您问题出在在您的代码中,它不是编译器方面的错误声明。有人可能会争辩说该语言应该允许这样的代码,但你必须向标准委员会提出这个问题。我同意您观察到的行为有些愚蠢。但是规则就是规则,如果没有额外的语法,这种行为就不能安全地添加到 C++ 中。这将产生极其意想不到的后果;事实上,这将是非常危险的。 【参考方案1】:

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

您可以申请Constexpr If(C++17 起)。

如果值为true,则丢弃statement-false(如果存在),否则丢弃statement-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();

【讨论】:

【参考方案2】:

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

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

    解决方案 - 1

    如果您只能访问c++11,SFINE(即"Substitution Failure Is Not An Error")技术以及函数重载将是一种方法。这将仅根据T 的类模板TypedUserProperty&lt;T&gt; 类中的正确方法打开(即实例化) 实例化。

    #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

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

【讨论】:

以上是关于编译器错误`在if语句中分配不兼容的类型`[重复]的主要内容,如果未能解决你的问题,请参考以下文章

if语句和变量声明的MSVC语法错误[重复]

不兼容的类型:java.util.date [重复]

PHP:在if语句中分配多个变量

在 if 语句中分配 fopen 的结果

在 if 语句 c# 中分配变量

在if语句之后返回vs啥都不做[重复]