Difference on address of const reference to ternar

2020-03-21 09:52发布

问题:

I have a vague idea of what's going on here... and it has to do with this but I'm wondering why clang++ and g++ handle this differently. Where is the undefined behaviour arround here? Note: this has nothing to do with templates - I just use them to make the example more compact. It's all about the type of whatever.

#include <iostream>
#include <vector>

template <typename T>
void test()
{
    T whatever = 'c';


    const char a = 'a';

    std::cout << "begin: " << (void*)&a << std::endl;

    const char & me = (true ? a : whatever);

    std::cout << "ref:   " << (void*)&me << std::endl;
}

int main(int argc, char**argv)
{

    test<const char>();
    test<char>();

    return 0;
}

gcc output (tested up to 4.9.3):

begin: 0x7fffe504201f
ref:   0x7fffe504201f
begin: 0x7fffe504201e
ref:   0x7fffe504201f

clang 3.7.0 output:

begin: 0x7ffed7b6bb97
ref:   0x7ffed7b6bb97
begin: 0x7ffed7b6bb97
ref:   0x7ffed7b6bb97

回答1:

My answer from this other question from today covers your cases in detail. I'll avoid repeating myself and just summarize.

If we factor out the templates you have two cases. Case 1:

const char whatever = 'c';
const char a = 'a';
const char & me = (true ? a : whatever);

The second and third operands of the conditional operator are both "lvalue of type const char", so the result is "lvalue of type const char" designating the selected operand. Finally, const char & binds directly to "lvalue of type const char", so &me == &a.

For case 2:

char whatever = 'c';
const char a = 'a';
const char & me = (true ? a : whatever);

The second and third operand are "lvalue of type char" and "lvalue of type const char". The result of this is "lvalue of type const char" designating the selected operand. As before, const char &me binds directly to an lvalue of type const char, so &me == &a.

If a compiler prints different addresses for me and a in either case, it is a compiler bug.