【发布时间】:2019-02-21 12:17:26
【问题描述】:
我想将工厂函数模板的调用分派到一个基于返回类型部分专门化的结构:
#include <array>
template<typename Type, typename Enable=void>
struct make_it;
template<typename A>
struct make_it<std::array<A, 3>>
{
static std::array<A, 3> apply()
{
return {A{0}, A{1}, A{2}};
}
};
template<typename A>
struct make_it<std::array<A, 4>>
{
static std::array<A, 4> apply()
{
return {A{0}, A{0}, A{0}, A{0}};
}
};
template<typename T>
constexpr bool greater(T&& a, T&& b)
{
return a > b;
}
template<typename T, int N>
struct make_it<std::array<T, N>, std::enable_if_t<greater(N,4)>>
{
static std::array<T, N> apply()
{
return std::array<T,N>{};
}
};
template<typename Type>
Type make()
{
return make_it<Type>::apply();
}
int main()
{
auto a = make<std::array<double,3>>();
auto b = make<std::array<double,4>>();
auto c = make<std::array<double,5>>();
}
编译
g++ -O3 -std=c++2a -Wall -Wpedantic -Wunused-parameter -I /usr/include main.cpp -o main
使用g++ (GCC) 8.2.1 20181127 会导致错误
main.cpp: In instantiation of ‘Type make() [with Type = std::array<double, 5>]’:
main.cpp:49:41: required from here
main.cpp:42:32: error: incomplete type ‘make_it<std::array<double, 5>, void>’ used in nested name specifier
return make_it<Type>::apply();
SFINAE 线有问题吗
struct make_it<std::array<T, N>, std::enable_if_t<greater(N,4)>>
我认为这应该部分专门化 make_it,为所有 N > 4 启用模板。所以如果N == 5,这个模板就会变得“可见”,它肯定更适合调用
auto c = make<std::array<double,5>>();
比不完整的类型?这里发生了什么?
【问题讨论】:
-
我猜您使用的是
greater,因为<N > 4>会混淆解析器,但您可以改用<(N > 4)>。 -
@Quentin:谢谢这摆脱了
greater,但错误仍然存在。 -
请注意Clang compiles this fine。这可能需要语言律师!
-
@Quentin:好的,谢谢!
-
我相信这可以简化为
template<class> struct A; template<class T, int N> struct A<std::array<T, N>> {}; A<std::array<int, 4>> a;。
标签: c++ templates sfinae template-specialization