A bit inspired by this question
Having this code
#include <string>
template<class T>
struct A {
template <typename U> using NewA = A<U>;
constexpr A(T const& t){}
constexpr auto f() const {
return NewA{"bye"};
}
};
A(const char*) -> A<std::string>;
int main() {
A{"hello"}.f();
}
GCC 13.1 generates a lot of useless code (call std::string constructor/destructor most notably and some other stuff)
main:
sub rsp, 72
mov edx, OFFSET FLAT:.LC1+5
mov esi, OFFSET FLAT:.LC1
lea rax, [rsp+16]
mov rdi, rsp
mov QWORD PTR [rsp], rax
call void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) [clone .isra.0]
lea rax, [rsp+48]
mov edx, OFFSET FLAT:.LC2+3
mov esi, OFFSET FLAT:.LC2
lea rdi, [rsp+32]
mov QWORD PTR [rsp+32], rax
call void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) [clone .isra.0]
lea rdi, [rsp+32]
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose()
mov rdi, rsp
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose()
xor eax, eax
add rsp, 72
ret
If I replace this line return NewA{"bye"};
with return ::A{"bye"};
(which is suppose to be exactly the same from my opinion)
#include <string>
template<class T>
struct A {
template <typename U> using NewA = A<U>;
constexpr A(T const& t){}
constexpr auto f() const {
return ::A{"bye"};
}
};
A(const char*) -> A<std::string>;
int main() {
A{"hello"}.f();
}
the compiler is able to optimize everything into one xor
main:
xor eax, eax
ret
Is that some kind of "early version bug"? Clang can't even compile this code yet (doesn't support CTAD via alias).
UPD: Looks like at least GCC 10.1 can optimize everything perfectly