The following code, compiled with gcc 4.10.0 20140714 (experimental) using the flags -Wall -Wextra -std=c++11 -pedantic or - alternatively - -Wall -Wextra -std=c++1y -pedantic //----------------------- struct true_type { static const bool value = true; }; struct false_type { static const bool value = false; }; template<class T> T&& declval(); template<typename> struct check { typedef void type; }; template<typename T, typename Enable = void> struct has_public_f : false_type {}; template<typename T> struct has_public_f< T, typename check< decltype( declval<T&>().f() ) >::type > : true_type {}; struct Spub { public: void f(); }; struct Spriv { private: void f(); }; static_assert( has_public_f<Spub>::value, "Ouch"); static_assert(!has_public_f<Spriv>::value, "Ouch"); int main() {} //----------------------- is rejected with the following diagnostics: <quote> prog.cc: In instantiation of 'struct has_public_f<Spriv>': prog.cc:33:35: required from here prog.cc:30:30: error: 'void Spriv::f()' is private struct Spriv { private: void f(); }; ^ prog.cc:27:15: error: within this context > : true_type {}; ^ prog.cc:30:30: error: 'void Spriv::f()' is private struct Spriv { private: void f(); }; ^ prog.cc:27:15: error: within this context > : true_type {}; ^ prog.cc:30:30: error: 'void Spriv::f()' is private struct Spriv { private: void f(); }; ^ prog.cc:33:16: error: within this context static_assert(!has_public_f<Spriv>::value, "Ouch"); ^ prog.cc:33:1: error: static assertion failed: Ouch static_assert(!has_public_f<Spriv>::value, "Ouch"); ^ </quote> It seems that in this context there is no silent rejection of the partial specialization, albeit it should.
Clang accepts the code.
EDG accepts it too.
I think I encountered a variant of this bug. Using this new awesome -fconcept feature, you can do the following: ``` template <typename type_t> struct type_trait; template <> struct type_trait<int> { static constexpr auto length = 0; }; template <> struct type_trait<long> { private: static constexpr auto length = 0; }; template <typename type_t> concept bool has_length = requires(type_t a) { { type_trait<type_t>::length }; }; int main() { static_assert(!has_length<char>); // expect: false, has no ::length static_assert(has_length<int>); // expect: true, has ::length static_assert(!has_length<long>); // expect: false, ::length is non-visible // but, last one fails in a compiler error return 0; } ``` This example asks whether a type_trait is defined for a given type. And it would be super useful to be able to express this. I think gcc uses internally SFINAE to check this but unfortunately fails because of this bug (probably).
This is still present on trunk, and causing issues for libc++ when trying to use void_t expressions in deduction guides.
http://lab.llvm.org:8011/builders/libcxx-libcxxabi-x86_64-linux-ubuntu-gcc-tot-latest-std/builds/310/steps/test.libcxx/logs/FAIL%3A%20libc%2B%2B%3A%3Adeduct.pass.cpp
Author: jason Date: Mon Jun 4 15:16:00 2018 New Revision: 261151 URL: https://gcc.gnu.org/viewcvs?rev=261151&root=gcc&view=rev Log: PR c++/61806 - missed SFINAE with partial specialization. * cp-tree.h (deferring_access_check_sentinel): Add deferring_kind parameter to constructor. * pt.c (instantiate_class_template_1): Enable access checking before call to most_specialized_partial_spec. Added: trunk/gcc/testsuite/g++.dg/cpp0x/sfinae63.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/pt.c
Author: jason Date: Mon Jun 11 22:02:19 2018 New Revision: 261464 URL: https://gcc.gnu.org/viewcvs?rev=261464&root=gcc&view=rev Log: PR c++/61806 - missed SFINAE with partial specialization. * cp-tree.h (deferring_access_check_sentinel): Add deferring_kind parameter to constructor. * pt.c (instantiate_class_template_1): Enable access checking before call to most_specialized_partial_spec. Added: branches/gcc-8-branch/gcc/testsuite/g++.dg/cpp0x/sfinae63.C Modified: branches/gcc-8-branch/gcc/cp/ChangeLog branches/gcc-8-branch/gcc/cp/cp-tree.h branches/gcc-8-branch/gcc/cp/pt.c
Fixed for 8.2.
*** Bug 80475 has been marked as a duplicate of this bug. ***