По-видимому, 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 просто отлично работает.