cig*_*ien 8 c++ templates language-lawyer
考虑以下代码:
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() {}
Run Code Online (Sandbox Code Playgroud)
gcc 接受了这一点,但 clang 拒绝了它:
error: out-of-line definition of 'f' does not match any declaration in 'S<T>'
Run Code Online (Sandbox Code Playgroud)
之前已经问过这个问题,但那里没有答案。
另一方面,如果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() {}
Run Code Online (Sandbox Code Playgroud)
clang 接受了这一点,但 gcc 拒绝了以下代码:
error: no declaration matches 'void S<T>::f()'
Run Code Online (Sandbox Code Playgroud)
那么这些片段中的任何一个都有效吗?
在定义过程中S<X>它是一个不完整类型。并且类成员访问运算符需要完整的类型。
但你可以用下面的代码解决这个问题:
#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() {}
Run Code Online (Sandbox Code Playgroud)