如何为所有“ std :: array”的工厂结构进行部分专业化,该结构超过4`元素
How to partially specialize a factory struct for all `std::array`s with more than `4` elements?
我想将呼叫从工厂功能模板派遣到基于返回类型的部分专业化的结构:
#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
启用tempplate。因此,如果N == 5
,此模板变为"可见",并且肯定适合调用
auto c = make<std::array<double,5>>();
比不完整的类型?这里发生了什么?
我不知道谁是正确的(G 会出现错误或编译的clang ),但我在您的代码中看到了不完美:您拦截了std::array
的大小,也就是 std::size_t
,因此无符号整数,作为 int
,一个签名的整数。
如果您编写了部分专业化,以拦截正确类型的值std::size_t
,
// ..................VVVVVVVVVVV (not int)
template<typename T, std::size_t N>
struct make_it<std::array<T, N>, std::enable_if_t<(N > 4)>>
{
static std::array<T, N> apply()
{
return std::array<T,N>{};
}
};
或作为auto
,如果您可以使用C 17,
// ..................VVVV
template<typename T, auto N>
struct make_it<std::array<T, N>, std::enable_if_t<(N > 4)>>
{
static std::array<T, N> apply()
{
return std::array<T,N>{};
}
};
您可以看到您的代码都与两个编译器一起编译。
您的模板类型与数组的类型不匹配(int
vtus std::size_t
)。
作为替代方案,当您使用C 17时,您可以使用:
template<typename T, std::size_t N>
struct make_it<std::array<T, N>>
{
static_assert(N >= 3); // As you don't provide specialization for those cases.
static std::array<T, N> apply()
{
if constexpr(N == 3) {
return {{T(0), T(0), T(0)}};
} else if constexpr(N == 4) {
return {{T(0), T(0), T(0), T(0)}};
} else if constexpr(N > 4) {
return {};
}
}
};
相关文章:
- 如何循环打印顶点结构
- 通过方法访问结构
- 如何使用默认参数等选择模板专业化
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 模板化建造师专业化
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 在模板专业化期间,如何设置C 结构中的静态字段
- 可以在模板专业化中互换使用类和结构
- 将enable_if与结构专业化
- 如何为所有“ std :: array”的工厂结构进行部分专业化,该结构超过4`元素
- 模板结构专业化使用TypName ::
- 模板中依赖于模板类型的结构的专业化