提问者:小点点

约束成员模板的出格定义有什么规则?


请考虑以下代码:

template <typename T>
struct S 
{
    template <typename = void>
    static constexpr bool B = true;

    template <std::enable_if_t<S<T>::template B<>, int> = 0>
    void f();
};

template <typename T>
template <std::enable_if_t<S<T>::template B<>, int>>
void S<T>::f() {}

gcc接受了这一点,但clang拒绝了它:

error: out-of-line definition of 'f' does not match any declaration in 'S<T>'

这个以前也有人问过,但那里没有答案。

另一方面,如果b不是模板,并且我编写了以下代码:

template <typename T>
struct S 
{
    static constexpr bool B = true;

    template <std::enable_if_t<S<T>::B, int> = 0>
    void f();
};

template <typename T>
template <std::enable_if_t<S<T>::B, int>>
void S<T>::f() {}

clang接受这一点,但gcc拒绝使用以下代码:

error: no declaration matches 'void S<T>::f()'

那么这些片段中的任何一个是否有效呢?


共1个答案

匿名用户

s的定义过程中,它是一个不完整的类型。并且类成员访问运算符需要完整的类型。

但您可以使用以下代码解决此问题:

#include <type_traits>

template <typename T>
struct S {

    template <typename = void>
    static constexpr bool B = true;

    template <
        typename TX = T,
        std::enable_if_t<S<TX>::template B<>, int> = 0>
    void f();
};

template <typename T>
template <typename TX, std::enable_if_t<S<TX>::template B<>, int>>
void S<T>::f() {}

//-----------

template <typename T>
struct S2 {

    static constexpr bool B = true;

    template <
        typename TX = T,
        std::enable_if_t<S2<TX>::B, int> = 0>
    void f();
};

template <typename T>
template <typename TX, std::enable_if_t<S2<TX>::B, int>>
void S2<T>::f() {}