[英]Accepting nested variadic class templates as arguments to function template
我正在嘗試創建一個函數模板,它將接受下面列出的兩個(或更多)嵌套的可變參數類模板作為參數,並將它們放入另一個將接受不同類型的數據結構中(對或元組就是我要做的)最有可能使用)。 以下是類和子類,以及我的函數的用法(該函數在下面進一步定義):
template<typename... Args> struct Entity {
template<typename... InnerEntArgs> struct InnerEntity {
InnerEntity(InnerEntArgs... inner_ent_args) {
... //do stuff w/ InnerEntArgs pack
... //do stuff that makes Inner dependent on Outer's Args pack
}
};
};
struct ThingA : Entity<int, string> {
... //construct ThingA
};
struct ThingB : Entity<string, string> {
... //construct ThingB
};
auto foo = my_func(
ThingA::InnerEntity<int, int, int>(1, 2, 3)
, ThingB::InnerEntity<string, int>("bar", 1)
);
下面是我拼湊的函數代碼,它編譯得很好,但我不確定它是否設置正確。 具體來說,我對typename
和::template
如何使編譯器在此上下文中感到滿意,或者如果此函數的行為方式與我期望的方式有點模糊:
template<
typename... ArgsA, typename... ArgsAInner
, typename... ArgsB, typename... ArgsBInner
> auto my_func(
typename Entity<ArgsA...>::template InnerEntity<ArgsAInner...> A
, typename Entity<ArgsB...>::template InnerEntity<ArgsBInner...> B
) -> tuple<decltype(A), decltype(B)> {
return make_tuple(A, B);
}
我想我已經很好地掌握了如何推導/推斷參數包,以及auto
, decltype
和尾隨返回類型如何做他們的事情,但如果我弄錯了,請讓我知道如何。
此外,如果有人想要證明這個函數的可變版本可以接受任意數量的嵌套可變參數類模板並將它們放入合適的容器或數據結構中,那就太好了,但我主要關心的是完全理解typename
和::template
。 提前謝謝!
*如果我錯誤地說了這個標題,或者我正在混淆條款,請解釋一下。 :)我在這里學習。
這不起作用,因為Entity<Args>::InnerEntity
是一個非推斷的上下文。 意味着ArgsA...
和ArgsAInner...
無法推斷,同樣對於其他參數。 這是因為之前的編譯器可以推斷出Args
,它必須知道什么類型的InnerEntity
是的一員,但是要知道 ,它必須根據Args
。
您可以將此函數作為友元函數模板放入Entity<Args...>
,只要兩者都是同一模板的成員,就可以使其工作。 但是上次我檢查時,GCC沒有找到類模板中定義的友元函數。
template<typename ...Args>
class Entity {
template<typename ...ArgsInner>
class InnerEntity {
};
template<typename ...ArgsAInner, typename... ArgsBInner>
> friend auto my_func(
InnerEntity<ArgsAInner...> A
, InnerEntity<ArgsBInner...> B
) -> tuple<decltype(A), decltype(B)> {
return make_tuple(A, B);
}
};
您還可以在InnerEntity
中聲明一些指定外部類類型的成員typedef, InnerEntity
根據該類型制定my_func
,以便SFINAE可以為非成員對其進行排序。
template<typename ...Args>
class Entity {
template<typename ...ArgsInner>
class InnerEntity {
typedef Entity outer_entity;
};
};
template<typename A, typename B, typename Result>
struct require_entity { };
template<typename ...ArgsA, typename ...ArgsB, typename Result>
struct require_entity<Entity<ArgsA...>, Entity<ArgsB...>> {
typedef Result type;
};
template<template<typename...> class AInner, template<typename...> class BInner,
typename ...ArgsAInner, typename ...ArgsBInner>
> auto my_func(
AInner<ArgsAInner...> A
, BInner<ArgsBInner...> B
) -> typename require_entity<
typename AInner<ArgsAInner...>::outer_entity,
typename BInner<ArgsBInner...>::outer_entity,
tuple<decltype(A), decltype(B)>>::type
{
return make_tuple(A, B);
}
當然,如果你不需要訪問ArgsAInner
類型,就像上面的my_func
一樣,你不需要那個template<typename...> class AInner
my_func
。 在這種情況下,你最好只接受typename AInner
並且寫得更少。 SFINAE仍將確保只接受正確的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.