-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Description
i notice that following program fails to compile:
template <typename> struct templ_foo;
template <> class templ_foo<int> {
void bar_func(bool);
};
template <> class templ_foo<bool> {
public:
template <class U>
auto maybe_call_foo(U u, bool set)
-> decltype(u.bar_func(set)) {
u.bar_func(set);
}
template <class U> void maybe_call_foo(U...);
};
template <class U>
auto maybe_call_foo(U u, bool set)
-> decltype(u.bar_func(set)) {
u.bar_func(set);
}
template <class U> void maybe_call_foo(U...);
void parse_format_specs() {
templ_foo<int> foo_int;
#define GLOBAL_OVERLOAD 0
#if GLOBAL_OVERLOAD
maybe_call_foo(foo_int, true);
#else
templ_foo<bool> foo_bool;
foo_bool.maybe_call_foo(foo_int, true);
#endif
}
when i compile it using Clang (tested with clang-16, clang-17 and the latest clang trunk):
$ clang++ -Werror -c -std=c++20 test.cc
test.cc:12:7: error: 'bar_func' is a private member of 'templ_foo<int>'
u.bar_func(set);
^
test.cc:33:12: note: in instantiation of function template specialization
'templ_foo<bool>::maybe_call_foo<templ_foo<int>>' requested here
foo_bool.maybe_call_foo(foo_int, true);
^
test.cc:4:8: note: implicitly declared private here
void bar_func(bool);
^
test.cc:11:21: error: 'bar_func' is a private member of 'templ_foo<int>'
-> decltype(u.bar_func(set)) {
^
test.cc:4:8: note: implicitly declared private here
void bar_func(bool);
^
2 errors generated.
but if i
#define GLOBAL_OVERLOAD 1
the source code compiles. the same source code compiles with gcc 13.2.1 with GLOBAL_OVERLOAD
defined to 1
or 0
.
my guess is that clang fails to take the member access check into consideration if the member is accessed by the template specialization of the same template. in this case, both full specializations specialize the template of templ_foo
with int
and bool
respectively. if i declare another template templ_baz
, and specialize it using bool
, and then define the same overloads in it, clang is able to sfinae out the overload accessing the private member function.
the reproducer is also available at godbolt. see https://godbolt.org/z/EW6EPPqz3
EDIT, i changed the code in the description of this issue to match the one in the godbolt. i was experimenting the case where the caller was a specialization of another template.