递归解包一个无参数函数的模板包。

问题描述 投票:0回答: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 parameter-pack
1个回答
1
投票

对于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时,这个模板才会被考虑。

演示

© www.soinside.com 2019 - 2024. All rights reserved.