Skip to content

"private" access specifier not respected in overloaded SFINAE context #107629

@HexadigmSystems

Description

@HexadigmSystems

Given the following code (run it here), where "Base::Whatever" is private (both overloads), why does Clang correctly display false except when (both) "T" is "Derived" and function "Whatever" is overloaded. This appears to be erroneous behavior but it's a fuzzy area in this context (but see behavior table further below):

#include <type_traits>
#include <iostream>

class Base
{
private: // Defaults to this anyway but being explicit

    void Whatever(int)
    {
    }

    void Whatever(int, float)
    {
    }
};

class Derived : public Base
{
};

template <typename T, typename U, typename = void>
struct HasFuncWhatever : std::false_type
{
};

template <typename T, typename U>
struct HasFuncWhatever<T,
                       U,
                       std::void_t<decltype(static_cast<U T::*>(&T::Whatever))>
                      >
                      : std::true_type
{
};

int main()
{
    using T = Derived;
    using U = void (int);
    std::cout << std::boolalpha << HasFuncWhatever<T, U>::value;
    return 0;
}

Here's the behavior of the 3 compilers I tested (only MSVC presumably gets it right):

T          "Whatever" overloaded?   Clang Displays    MSVC Displays     GCC Displays       
-          ----------------------   --------------    -------------     ------------
Base       No                       false (correct)   false (correct)   false (correct)    
Base       Yes                      false (correct)   false (correct)   Fails compilation due to private access (incorrect)
Derived    No                       false (correct)   false (correct)   false (correct)  
Derived    Yes                      true (incorrect)  false (correct)   Fails compilation due to private access (incorrect)

Unless this is explicitly mentioned in the standard somewhere, or it's considered undefined behavior (implementation defined), the call to "&T::Whatever" in the partial specialization of "HasFuncWhatever" should always presumably fail since "Whatever" is private. The primary template should therefore always kick in so the code should always display false.

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions