gpt4 book ai didi

C++ 模板参数包别名扩展

转载 作者:行者123 更新时间:2023-12-02 03:35:08 29 4
gpt4 key购买 nike

所以,我的动机是确定多个类中相同的命名类型声明是否是相同的类型。在此示例中,我希望看到所有 Foo、Bar 和 Baz 都有一个内部类型 Q。

#include <type_traits>

template <typename N,typename ...Ns>
using equal_type_t = typename std::enable_if_t<(std::is_same_v<N, Ns> && ...), N>;

template <typename N>
using ExtractQ_t = typename N::Q;

template <typename ...Ns>
using EqualQ_t = equal_type_t<ExtractQ_t<Ns>...>;


int main()
{
struct Qness{};
struct Foo{using Q = Qness;};
struct Bar{using Q = Qness;};
struct Baz{using Q = Qness;};
using F = EqualQ_t<Foo,Bar,Baz>;
static_assert(std::is_same_v<F,Qness>);

return 0;
}

在 clang9 中测试(赞美 godbolt)。

报告的错误是:

#1 with x86-64 clang 9.0.0
<source>:10:31: error: pack expansion used as argument for non-pack parameter of alias template

using EqualQ_t = equal_type_t<ExtractQ_t<Ns>...>;

我可能可以通过进行一些模板递归来解决这个问题,但我正在尝试学习尽可能使用参数包扩展。

这可能吗?这不是允许的上下文吗?如果我分离出一些单独的 N 类型,它就可以正常工作:

template <typename N1,typename N2, typename N3, typename ...Ns>
using EqualQ_t = equal_type_t<ExtractQ_t<N1>,ExtractQ_t<N2>,ExtractQ_t<N3>>;

我必须在喝咖啡前脑子一片迷茫,看不出我可能在哪里使用语法。

是否有可以使用的扩展变体?

最佳答案

错误诊断试图表明 equal_type_t 的第一个参数不能是包,但您正在将包扩展到其中。因此,简单的修复方法就是执行与之前相同的操作:

template <typename N, typename ...Ns>
using EqualQ_t = equal_type_t<ExtractQ_t<N>, ExtractQ_t<Ns>...>;

https://godbolt.org/z/j6_HGU

解包为非包 + 包需要模板参数推导,但别名模板不会发生这种情况,请参阅 cppreference 。您需要结构模板专门化(或模板函数调用)才能获得推导。

<小时/>

不过在这种情况下使用 SFINAE 似乎有点奇怪。如果不满足条件,您会得到一些compiler gibberish关于 SFINAE 扔在你脸上。还有其他方法会在编译过程中导致硬错误。

我想说以下是编写相同代码的惯用方法,当出现问题时它会给你一个很好的错误,并且会(不完全巧合)避免你原来的问题:

template <typename ...Ns>
struct equal_type;

template <typename N,typename ...Ns>
struct equal_type<N, Ns...>
{
static_assert((std::is_same_v<N, Ns> && ...), "These types must be the same!");
using type = N;
};

template <typename ...Ns>
using equal_type_t = typename equal_type<Ns...>::type;

template <typename N>
using ExtractQ_t = typename N::Q;

template <typename ...Ns>
using EqualQ_t = equal_type_t<ExtractQ_t<Ns>...>;

https://godbolt.org/z/u52mUE

<小时/>

为了完整起见,C++17 之前的方式(在折叠表达式存在之前)确实使用了递归:

template <typename N1, typename N2, typename ...Ns>
struct equal_type
{
static_assert(std::is_same_v<N1, N2>, "These types must be the same!");
using type = typename equal_type<N1, Ns...>::type;
};

template <typename N1, typename N2>
struct equal_type<N1, N2>
{
static_assert(std::is_same_v<N1, N2>, "These types must be the same!");
using type = N1;
};

https://godbolt.org/z/NKmMZD

关于C++ 模板参数包别名扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58308189/

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