其他分享
首页 > 其他分享> > c三元运算符转换理解

c三元运算符转换理解

作者:互联网

我无法理解这个三元运算符的转换逻辑(这里是一个例子):

#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< T>,它是任何类型的包装器,用于案例,与此问题无关,并且有一个转换运算符到T.问题是当singletime< uint64_t>用于三元运算符表达式.

这是有问题的一行:

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

唯一的问题是当三元运算符与单一时间< uint64_t>一起使用时. – 它的值为18446744071562067968

据我了解,它试图将不同类型转换为一种类型.

由于来自单一时间的转换运算符< uint64_t>对于uint64_t,它可能会使用它,但之后我不明白为什么它将两个值都转换为int而不是uint64_t?在使用uint64_t而不是singletime< uint64_t>的示例中,int转换为uint64_t并且没有值丢失

在单一时间< uint64_t>的情况下和int,也没有关于强制转换为较小类型和潜在数据丢失的编译器警告.

尝试使用gcc 4.8.2和gcc 5.2.0

解决方法:

从标准,5.16.

if the second and third operand have different types, and either has
(possibly cv-qualified) class type, an attempt is made to convert each
of those operands to the type of the other. The process for determining whether an operand expression E1 of type T1 can be converted to
match an operand expression E2 of type T2 is defined as follows:

If E2 is an rvalue, or if the conversion above cannot be done:

Otherwise (i.e., if E1 or E2 has a nonclass type, or if they both have
class types but the underlying classes are not either the same or one
a base class of the other): E1 can be converted to match E2 if E1 can
be implicitly converted to the type that expression E2 would have if
E2 were converted to an rvalue (or the type it has, if E2 is an
rvalue).

If the second and third operand do not have the same type, and either
has (possibly cv-qualified) class type, overload resolution is used to
determine the conversions (if any) to be applied to the operands
(13.3.1.2, 13.6).

所以,这里,0是rvalue,它的类型为int.编译器会尝试将第一个参数转换为int,它会这样做,因为你的转换操作符可以完成.

标签:c,implicit-conversion
来源: https://codeday.me/bug/20190823/1701298.html