По-видимому, clang считает, что decltype(this) является указателем на класс cv-qual, а gcc считает, что это ссылка const на указатель на класс cv-qualified. GCC думает, что decltype(&*this) является указателем на класс cv. Это имеет некоторые последствия, когда оно используется в качестве имени шаблона для шаблона. Рассмотрим гипотетический пример:
template<typename T>
class MyContainer {
/* ... */
template<typename ContainerPtr>
class MyIterator {
ContainerPtr container;
/* ... */
};
auto cbegin() const
-> MyIterator<decltype(&*this)> { return { /* ... */ }; }
auto cend() const
-> MyIterator<decltype(this)> { return { /* ... */ }; }
};
В этом примере один реализует пользовательский контейнер T. Являясь контейнером, он поддерживает итераторы. На самом деле два типа итераторов: iterator и const_iterator s. Было бы нецелесообразно дублировать код для этих двух, поэтому можно было бы написать класс итератора шаблона, взяв либо указатель на исходный класс MyContainer<T> *, либо указатель на версию const MyContainer<T> const *.
Когда cbegin и cend используются вместе, gcc ошибается, говоря, что он выводил конфликтующие типы, в то время как clang просто отлично работает.