dom*_*m00 6 c++ templates variadic-templates
C++ 可变参数模板可以使用模式,您可以在其中重复可变参数参数周围的块,如下所示:
template<typename... Args>
struct MyStruct : seq<pair<Other, Args>...>
MyStruct<X, Y> // expands to seq<pair<Other, X>, pair<Other, Y>>
Run Code Online (Sandbox Code Playgroud)
然而,据我所知,所有这些模式扩展都需要(并保留)一个封闭块。我正在寻找扩展inline模式,如下所示:
template<typename... Args>
struct MyStruct : seq<???Other, Args???...>
MyStruct<X, Y> // expands to seq<Other, X, Other, Y>
Run Code Online (Sandbox Code Playgroud)
有没有办法达到这样的效果呢?
如果您喜欢自己进行元编程,则可以使用四个实用程序重载来完成该行为。
就像另一个答案指出的那样,关键是连接seq类型,因此我们的实用程序将做到这一点。需要理解的重要一点是,元编程本质上主要是函数式的,因此工具将是递归和模式匹配(所有这些都在重载解析期间)。以下是重载:
namespace detail {
auto seq_concat() -> seq<>&;
template<typename... Args>
auto seq_concat(seq<Args...>&) -> seq<Args...>&;
template<typename... Args, typename... Brgs>
auto seq_concat(seq<Args...>&, seq<Brgs...>&) -> seq<Args..., Brgs...>&;
template<class Seq, class... Seqs>
auto seq_concat(Seq& s, Seqs&... ss) -> decltype(seq_concat(s, seq_concat(ss...)));
}
Run Code Online (Sandbox Code Playgroud)
前三个是我们的“基本情况”。当连接零到两个seq时,我们明确地列出了我们应该得到的类型,而最终的重载是我们的一般情况。连接三个或更多“类序列”类型的列表,是将元素集中在列表尾部,然后获取该结果并将其与列表头连接。
现在我们可以编写您需要的实用程序,因为要创建 aseq<Other, A, Other, B>我们可能只需连接seq<Other, A>,seq<Other, B>并且如果我们需要更多类型,我们可以对seq<Other, Args>...所有这些进行包扩展并连接。
struct Other;
template<typename... Args>
using seq_interleave_with_other = typename std::remove_reference<decltype(detail::seq_concat(std::declval<seq<Other, Args>&>()...))>::type;
Run Code Online (Sandbox Code Playgroud)
我们创建一个模式std::declval<seq<Other, Args>&>()...来“为我们提供对对象的引用”,我们可以在未评估的上下文中使用,然后调用detail::seq_concat(...)该模式。返回类型(几乎)是我们所需要的,因为我们的实用程序添加了引用以简化实现它们。快速浏览一下std::remove_reference,我们就完成了。要使用它,只需编写:
template<typename... Args>
struct MyStruct : seq_interleave_with_other<Args...>
{};
Run Code Online (Sandbox Code Playgroud)