无法使用 std::enable_if 在 g++/clang++ 上编译显式专用模板结构
Failing to compile explicitly specialized template struct on g++/clang++ with std::enable_if
我尝试用 msvc 编译它并且编译正常。另一方面,我没能用 g++ 和 clang++ 编译它。我得到的错误是 no type named ‘type’ in ‘struct std::enable_if<false, void>’
。我该如何解决这个错误?
#include <type_traits>
template <bool v>
struct a {
template <typename T = typename std::enable_if<v>::type>
void function();
};
template struct a<false>;
template struct a<true>;
template<bool v>
template<typename T>
void a<v>::function() { }
int main() {
}
如果通过 bool
模板是 true
,我正在尝试使 void function
可见。
您没有正确使用 SFINAE,因为您传递给 enable_if
(即 v
)的 bool
不依赖于函数模板参数。
有选择地添加或删除 class 模板成员的规范方法是使用模板专业化。例如:
template <bool v>
struct a {
void function();
};
template< >
struct a<false> {
};
现在,只有 a<true>
会有 function
成员。如果您有许多共同成员应该出现在 a
中,而不管 v
,您可以将这些成员移动到基础 class 并从中派生两个特化:
struct a_common {
void common_function();
};
template <bool v>
struct a : public a_common {
void function();
};
template< >
struct a<false> : public a_common {
};
这也可以通过 SFINAE 实现,但需要一些技巧。上面说了,我们需要把function
做成模板,需要保证enable_if
中使用的条件依赖于它的模板参数。由于我们没有任何模板参数,因此我们需要添加一个虚拟参数:
template <bool v>
struct a {
template<
typename Dummy = void,
typename = typename std::enable_if<
std::is_same< Dummy, Dummy >::value && v
>::type
>
void function();
};
这里,我们在计算enable_if
的第一个模板参数时,使用is_same
trait引入对Dummy
模板参数的形式依赖。自然地,is_same
的结果将是true
,因此v
有效地决定了function
模板是否可以被实例化。
我尝试用 msvc 编译它并且编译正常。另一方面,我没能用 g++ 和 clang++ 编译它。我得到的错误是 no type named ‘type’ in ‘struct std::enable_if<false, void>’
。我该如何解决这个错误?
#include <type_traits>
template <bool v>
struct a {
template <typename T = typename std::enable_if<v>::type>
void function();
};
template struct a<false>;
template struct a<true>;
template<bool v>
template<typename T>
void a<v>::function() { }
int main() {
}
如果通过 bool
模板是 true
,我正在尝试使 void function
可见。
您没有正确使用 SFINAE,因为您传递给 enable_if
(即 v
)的 bool
不依赖于函数模板参数。
有选择地添加或删除 class 模板成员的规范方法是使用模板专业化。例如:
template <bool v>
struct a {
void function();
};
template< >
struct a<false> {
};
现在,只有 a<true>
会有 function
成员。如果您有许多共同成员应该出现在 a
中,而不管 v
,您可以将这些成员移动到基础 class 并从中派生两个特化:
struct a_common {
void common_function();
};
template <bool v>
struct a : public a_common {
void function();
};
template< >
struct a<false> : public a_common {
};
这也可以通过 SFINAE 实现,但需要一些技巧。上面说了,我们需要把function
做成模板,需要保证enable_if
中使用的条件依赖于它的模板参数。由于我们没有任何模板参数,因此我们需要添加一个虚拟参数:
template <bool v>
struct a {
template<
typename Dummy = void,
typename = typename std::enable_if<
std::is_same< Dummy, Dummy >::value && v
>::type
>
void function();
};
这里,我们在计算enable_if
的第一个模板参数时,使用is_same
trait引入对Dummy
模板参数的形式依赖。自然地,is_same
的结果将是true
,因此v
有效地决定了function
模板是否可以被实例化。