gpt4 book ai didi

c++ - 为什么 clang 无法使用默认的 integer_sequence 实例化嵌套的可变参数模板?

转载 作者:可可西里 更新时间:2023-11-01 15:27:42 26 4
gpt4 key购买 nike

考虑一个例子:

#include <utility>

template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class P, class = std::make_index_sequence<P::size>>
struct ipack;

template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack;

template <class... Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

int main() {
vpack<ipack<pack<int, int, int>>> vp;
static_cast<void>(vp);
}

铿锵 reports一个问题:

prog.cc:29:39: error: implicit instantiation of undefined template 'vpack<ipack<pack<int, int, int>, std::__1::integer_sequence<unsigned long, 0, 1, 2> >, std::__1::integer_sequence<unsigned long, 0, 1, 2>
vpack<ipack<pack<int, int, int>>> vp;
^

海湾合作委员会does not share铿锵的感觉在这里。哪个编译器是正确的?上面的代码在某种程度上是错误的吗?

最佳答案

我无法使用 godbolt 重现您的错误. Clang 和 gcc 编译它就好了。

然而,在使用编译器时,我发现 msvc 不喜欢你的代码,因为 ipack 中的默认参数.但是,如果您直接提供参数,它会起作用:

template <class...Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>,std::index_sequence<Is...>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

此更改也修复了您的 clang 错误。 (我不知道如何在 wandbox 中获取链接...)

编辑:

msvc 指出了另一个错误,我在上面省略了。 vpack必须是可构造的。但是,因为您刚刚声明了它 ( struct vpack; ),所以没有可用的默认构造函数。您可以通过定义它来解决此问题,使用:struct vpack {}; .这也解决了 clang 问题。 (即使没有上述内容。)

编辑 2:

思考为什么需要使用struct vpack {};我在您的代码中发现了另一个缺陷。它可以简化为:

#include <utility>

template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class P, class = std::make_index_sequence<P::size>>
struct ipack {};

template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack {};

int main() {
vpack<ipack<pack<int, int, int>>> vp;
static_cast<void>(vp);
}

原因是,您的模板特化 vpack没有被实例化,是因为您使用的是主模板的默认参数。 (vpack<ipack<pack<int, int, int>>> 只提供一个参数,而不是特化所需的两个参数。)

您甚至可以删除 ipack 的模板特化,如果不是因为您在 vpack 中隐含地使用它基本的。 ( IP::size 指的是 ipack 的特化。)

(我写了一个版本:https://godbolt.org/g/6Gbsvd)

因此,msvc 和 wandboxes clang 拒绝编译您的代码是正确的。我不确定为什么它在 gcc 和 godbolts clang 下工作。它可能与处理默认参数的方式有关...

有趣的是,您可以通过定义 size 来看出差异在vpack里面初级:

#include <utility>

template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class P, class = std::make_index_sequence<P::size>>
struct ipack;

template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack { static constexpr std::size_t size = 0; };

template <class... Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>,std::make_index_sequence<sizeof...(Ts)>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};

int main() {
vpack<ipack<pack<int, int, int>>> vp;

return decltype(vp)::size;
}

gcc 和 clang 返回 3 , 但 msvc 返回 0 .

关于c++ - 为什么 clang 无法使用默认的 integer_sequence 实例化嵌套的可变参数模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43469865/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com