La clase no puede acceder a su propio método constexpr estático privado - ¿Error de Clang?

28

Este código no se compila en Clang (6,7,8,9, troncal), pero se compila muy bien en GCC (7.1, 8.1, 9.1):

template<class T> struct TypeHolder { using type = T; };

template<int i>
class Outer {
private:
    template<class T> 
    static constexpr auto compute_type() {
        if constexpr (i == 42) {
            return TypeHolder<bool>{};
        } else {
            return TypeHolder<T>{};
        }
    }

public:
    template<class T>
    using TheType = typename decltype(Outer<i>::compute_type<T>())::type;
};

int main() {
    Outer<42>::TheType<int> i;
}

Clang me dice:

<source>:17:49: error: 'compute_type' is a private member of 'Outer<42>'

... lo que por supuesto es, pero estoy tratando de acceder a ese miembro desde dentro de la misma clase. No veo por qué no debería ser accesible allí. ¿He golpeado (y debo presentar) un error de Clang?

Puedes jugar con el código en el explorador del compilador de Godbolt .

Lukas Barth
fuente
3
Aparentemente agregar friend int main();detiene a Clang de quejarse.
HolyBlackCat
2
¡Gracioso! Sin embargo, la verificación de acceso definitivamente debe hacerse con los "permisos" de Outer<42>, ¿no main? Ahora me parece aún más un error.
Lukas Barth
¿Usar el std::result_oftrabajo en su lugar?
Brandon
FWIW, también funciona en ICC y MSVC.
ChrisMM

Respuestas:

23

Este es el problema central 1554 . El estándar no está claro cómo se realiza la verificación de acceso para las plantillas de alias (en el contexto de la definición o en el contexto de uso).

La dirección actual es verificar en el contexto de la definición, lo que haría que su código esté bien formado.

TC
fuente