Публичный "using" = decltype (<private>)
В следующем (свернутом) коде у меня есть объявление публичного using
, которое ссылается на decltype(something_private)
: using Foo = decltype(something_private<T>)
.
На Clang, но не GCC, это не компилируется из-за того, что оно является закрытым.
Вопросы:
- Что является элегантным решением, если я не хочу делать
func<T>()
общедоступным. - Где в стандарте C++ (C++ 11) делает резервную Clang, чтобы быть здесь правильно?
Ниже код не работает со следующим кодом ошибки на Clang (3.9 - 7.0), но основывается на GCC (4.8.4 - 8.2):
class A {
private:
template <class T>
static auto func() -> T; // The actual return type is much
// more complicated, so 'using Foo = T' would not work.
public:
template <class T>
using Foo = decltype(func<T>());
};
int main(int, char**) {
A::Foo<int> y;
return y;
}
Выход Clang 7.0:
<source>:10:24: error: 'func' is a private member of 'A'
using Foo = decltype(func<T>());
^~~~~~~
<source>:14:7: note: in instantiation of template type alias 'Foo' requested here
A::Foo<int> y;
^
<source>:6:15: note: declared private here
static auto func() -> T;
^
1 error generated.
Compiler returned: 1
https://godbolt.org/z/zD4Hk5
Ответы
Ответ 1
Я не смотрел в стандарте для цитаты, но обходное решение для вас. Поскольку это работает, это заставляет меня думать, что у clang есть ошибка. Когда функция находится непосредственно в A, она рассматривает псевдоним типа, как если бы он был в контексте вызывающего, но перемещение функции в структуру решает это. Мех. Я сделал много g++/clang портирования в последнее время, и пока я не сталкивался с этим конкретно, он пахнул некоторыми вещами, с которыми я столкнулся.
class A {
private:
struct X {
template <class T>
static auto func() -> T;
};
public:
template <class T>
using Foo = decltype(X::func<T>());
};
void bar() {
A::Foo<int> y;
}
https://godbolt.org/z/ozIS-r
UPDATE: добавлена ссылка.
Я думаю, что это прямо ответит на ваш вопрос, и этот clang здесь не так.
N4778 (последнее, что я нашел), 10.8/p4 (pg 259)... [Примечание. Поскольку управление доступом применяется к именам, если контроль доступа применяется к имени typedef, рассматривается только доступность самого typedef. Доступность объекта, упомянутого в typedef, не рассматривается.