In the following (minimized) code, I have a public using
declaration that is referring to decltype(something_private)
: using Foo = decltype(something_private<T>)
.
On Clang but not GCC this does not compile because of it being private.
Questions:
func<T>()
public. The below code fails with the following error code on Clang (3.9 - 7.0) but builds on 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 output:
<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
I haven't looked at the standard for citation, but have a workaround for you. Because this works, it makes me think clang just has a bug. When the function is directly in A, it treats the type alias as if it were in the context of the caller, but moving the function into a struct solves that. Meh. I've done a lot of g++ / clang porting lately and while I didn't run into this specifically, it smelled of some things I encountered.
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;
}
UPDATE: added citation.
I think this directly answers your question, and that clang is wrong here.
N4778 (the latest I found), 10.8/p4 (pg 259) ... [Note: Because access control applies to names, if access control is applied to a typedef name, only the accessibility of the typedef name itself is considered. The accessibility of the entity referred to by the typedef is not considered.