Why do gcc and clang each produce different output for this program? (conversion operator vs constructor)

Viewed 4433

program:

#include <stdio.h>

struct bar_t {
    int value;
    template<typename T>
    bar_t (const T& t) : value { t } {}

    // edit: You can uncomment these if your compiler supports
    //       guaranteed copy elision (c++17). Either way, it 
    //       doesn't affect the output.

    // bar_t () = delete;
    // bar_t (bar_t&&) = delete;
    // bar_t (const bar_t&) = delete;
    // bar_t& operator = (bar_t&&) = delete;
    // bar_t& operator = (const bar_t&) = delete;
};

struct foo_t {
    operator int   () const { return 1; }
    operator bar_t () const { return 2; }
};

int main ()
{
    foo_t foo {};
    bar_t a { foo };
    bar_t b = static_cast<bar_t>(foo);

    printf("%d,%d\n", a.value, b.value);
}

output for gcc 7/8:

2,2

output for clang 4/5 (also for gcc 6.3)

1,1

It seems that the following is happening when creating the instances of bar_t:

For gcc, it calls foo_t::operator bar_t then constructs bar_t with T = int.

For clang, it constructs bar_t with T = foo_t then calls foo_t::operator int

Which compiler is correct here? (or maybe they are both correct if this is some form of undefined behaviour)

1 Answers
Related