【问题标题】:c++ ternary operator conversion understandingc++三元运算符转换理解
【发布时间】:2017-02-16 14:10:14
【问题描述】:

我看不懂这个三元运算符的转换逻辑(这里是一个例子):

#include <iostream>
#include <typeinfo>
#include <unistd.h>
#include <cxxabi.h>
#include <climits>

template<typename T>
struct singletime
{
private:
    T               value;
public: 
    T& operator()() {return this->value;}

    operator const  T& () const {return value;}
    unsigned char   flag_needed_for_all_types;
};

static void getvalue1 (uint64_t value, const char *call)
{
    std::cout << call << ": \t" << value << std::endl << std::endl;
}

#define getvalue(x, str) \
std::cout << typeid(x).name() << std::endl; \
getvalue1(x, str);

int main (int argc, char *argv[])
{
    bool flag = true;
    singletime<uint64_t> singletime_64;
    singletime_64() = INT_MAX+1lu;

    uint64_t value_64 = singletime_64;

    getvalue (flag ? singletime_64 : 0, "Ternary with singletime, > INT_MAX");
    getvalue (singletime_64, "singletime w/o ternary, > INT_MAX");

    getvalue (flag ? value_64 : 0, "Ternary with uint64_t, > INT_MAX");
    getvalue (value_64, "uint64_t w/o ternary, > INT_MAX");


    singletime_64() = INT_MAX;

    uint64_t value_64_l = singletime_64;

    getvalue (flag ? singletime_64 : 0, "Ternary with singletime, <= INT_MAX");
    getvalue (singletime_64, "singletime w/o ternary, <= INT_MAX");

    getvalue (flag ? value_64_l : 0, "Ternary with uint64_t, <= INT_MAX");
    getvalue (value_64_l, "uint64_t w/o ternary, <= INT_MAX");

    return 0;
}

我有一个模板类singletime&lt;T&gt;,它是任何类型的包装器,用于与此问题无关的案例,并且有一个到T 的转换运算符。问题是在三元运算符表达式中使用singletime&lt;uint64_t&gt; 时。

这是有问题的行:

getvalue (flag ? singletime_64 : 0, "Ternary with singletime, > INT_MAX");

64位值转换为int,如果大于INT_MAX,则变为不正确。

该示例打印了三元运算符的一些使用类型 - 以及表达式的结果类型和结果值。
这是示例的输出:

int
Ternary with singletime, > INT_MAX:     18446744071562067968

singletime<unsigned long>
singletime w/o ternary, > INT_MAX:  2147483648

unsigned long
Ternary with uint64_t, > INT_MAX:   2147483648

unsigned long
uint64_t w/o ternary, > INT_MAX:    2147483648

int
Ternary with singletime, <= INT_MAX:    2147483647

singletime<unsigned long>
singletime w/o ternary, <= INT_MAX:     2147483647

unsigned long
Ternary with uint64_t, <= INT_MAX:  2147483647

unsigned long
uint64_t w/o ternary, <= INT_MAX:   2147483647

唯一的问题是当三元运算符与 singletime&lt;uint64_t&gt; 一起使用时 - 它的值是 18446744071562067968

据我了解,它会尝试将不同类型转换为一种类型。

由于有从singletime&lt;uint64_t&gt;uint64_t 的转换运算符,它可能会使用它,但之后我不明白为什么它将两个值都转换为int,而不是uint64_t?在使用uint64_t 而不是singletime&lt;uint64_t&gt; 的示例中,int 被转换为uint64_t 并且没有值丢失

singletime&lt;uint64_t&gt; 和 int 的情况下,也没有关于强制转换为较小类型和潜在数据丢失的编译器警告。

尝试使用 gcc 4.8.2 和 gcc 5.2.0

【问题讨论】:

    标签: c++ implicit-conversion


    【解决方案1】:

    从标准,5.16。

    如果第二个和第三个操作数有不同的类型,并且任何一个都有 (可能是 cv 限定的)类类型,尝试转换每个 这些操作数的类型到另一个的类型。判断 T1 类型的操作数表达式 E1 是否可以转换为的过程 匹配 T2 类型的操作数表达式 E2 定义如下:

    如果 E2 是一个右值,或者上面的转换不能完成:

    否则(即,如果 E1 或 E2 具有非类类型,或者如果它们都具有 类类型,但基础类不是相同或一个 另一个的基类):如果 E1 可以,则 E1 可以转换为匹配 E2 隐式转换为表达式 E2 将具有的类型,如果 E2 被转换为右值(或它具有的类型,如果 E2 是 右值)。

    如果第二个和第三个操作数的类型不同,并且 具有(可能是 cv 限定的)类类型,重载决议用于 确定要应用于操作数的转换(如果有) (13.3.1.2, 13.6)。

    所以,这里的 0 是右值,它的类型为 int。编译器将尝试将第一个参数转换为 int 并且它会这样做,因为可以通过您的转换运算符来完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-13
      • 2015-03-25
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多