为无参数函数递归解压模板包
Recursively unpacking a template pack for a parameter-less function
我正在尝试创建一个带有可变模板类型包的结构模板,它可以扣除传入的所有类型的大小总和。
下面是一个简化的示例,在真实世界的上下文中,计算出的大小用于创建更多的成员对象。
template <typename... Types>
struct OverallSize
{
template <typename FirstType, typename... NextTypes>
static constexpr size_t sizesum() { return sizeof (FirstType) + sizesum<NextTypes...>(); }
template <typename LastType>
static constexpr size_t sizesum() { return sizeof (LastType); }
static constexpr size_t size = sizesum<Types...>();
};
// Should work e.g. like this
auto s = OverallSize<int, float, char>::size; // s will be 9 on x86-64
当涉及到参数列表时,我已经习惯了这种递归参数解包方法,并假设它也适用于无参数函数和显式模板规范。但是,在使用 clang
编译时出现以下错误
Call to 'sizesum' is ambiguous
...
Candidate function [with FirstType = unsigned long, NextTypes = <>]
Candidate function [with LastType = unsigned long]
所以似乎最后一个递归迭代在这里不起作用——不确定为什么编译器不简单地选择最明显的选择:只有一种模板类型的选择——就像如果有是传递给函数的实际模板参数。
那么,我需要做什么才能使它按预期编译和工作?
对于 C++14,您可以使用 SFINAE:
template <
typename FirstType,
typename... NextTypes,
std::enable_if_t<sizeof...(NextTypes) >= 1>* = nullptr >
static constexpr size_t sizesum() {
return sizeof (FirstType) + sizesum<NextTypes...>();
}
仅当参数包的大小 >= 1 时才会考虑此模板。
我正在尝试创建一个带有可变模板类型包的结构模板,它可以扣除传入的所有类型的大小总和。
下面是一个简化的示例,在真实世界的上下文中,计算出的大小用于创建更多的成员对象。
template <typename... Types>
struct OverallSize
{
template <typename FirstType, typename... NextTypes>
static constexpr size_t sizesum() { return sizeof (FirstType) + sizesum<NextTypes...>(); }
template <typename LastType>
static constexpr size_t sizesum() { return sizeof (LastType); }
static constexpr size_t size = sizesum<Types...>();
};
// Should work e.g. like this
auto s = OverallSize<int, float, char>::size; // s will be 9 on x86-64
当涉及到参数列表时,我已经习惯了这种递归参数解包方法,并假设它也适用于无参数函数和显式模板规范。但是,在使用 clang
编译时出现以下错误Call to 'sizesum' is ambiguous
...
Candidate function [with FirstType = unsigned long, NextTypes = <>]
Candidate function [with LastType = unsigned long]
所以似乎最后一个递归迭代在这里不起作用——不确定为什么编译器不简单地选择最明显的选择:只有一种模板类型的选择——就像如果有是传递给函数的实际模板参数。
那么,我需要做什么才能使它按预期编译和工作?
对于 C++14,您可以使用 SFINAE:
template <
typename FirstType,
typename... NextTypes,
std::enable_if_t<sizeof...(NextTypes) >= 1>* = nullptr >
static constexpr size_t sizesum() {
return sizeof (FirstType) + sizesum<NextTypes...>();
}
仅当参数包的大小 >= 1 时才会考虑此模板。