2

我有一个可变参数类模板,它有一个嵌套的可变参数类模板。外部类模板有一个函数模板,它接受任意数量的参数并将返回一个内部类型的对象。我的问题是创建一个完全独立的函数,该函数将接受这些内部类型的任意数量的任何变体(并且仅接受内部类型),而不管外部类型的变体如何,同时仍确保函数接受的类型是嵌套成员只有那个外部类模板。不确定我是否充分解释了......这基本上是我正在使用的内容:

template<typename... ArgsOuter> class Outer {
    typedef Outer<ArgsOuter...> outer_t;

    template<typename... ArgsInner> class Inner {
        //static const outer_t* outer;
        typedef outer_t outer;

        Inner(const ArgsInner&... args_inner) {
            //do stuff
        }
    };

    /*
      What's passed in here will be related to and will be a subset of
      the types used to define the Outer class, but I'm not really
      concerned about checking what's being passed in right now.
    */
    template<typename... ArgsFunc>
    make_inner(ArgsFunc... args_func) {
        return Inner<ArgsFunc...> (args_func...);
    }
};

struct ThingA : Outer<int, int, float> {
};

struct ThingB : Outer<int, string, int> {
};

struct ThingC : Outer<string, string, int, int> {
};

//struct ThingN : Outer<random types...> {}

//...meanwhile, over at main...

ThingA tA;
ThingB tB;
ThingC tC;

auto tA_inner = tA.make_inner(1, 1.1);
auto tB_inner = tB.make_inner(2, "foo");
auto tC_inner = tC.make_inner("bar", 2, "foobar");

//mystery_func() is the function I'm not sure how to define.
auto meatloaf = mystery_func(tA_inner, tB_inner, tC_inner);

有人对此有 SFINAE 或可变参数函数模板(或其他)解决方案吗?

4

2 回答 2

2

我认为这实际上可能是不可能的。您似乎想要的是能够执行以下操作:

template < typename ... Args1, typename ... Args2, typename ... Args3>
?? mystery_func(Inner<Args1...>,Inner<Args2...>,Inner<Args3...>);

我不认为你能做到这一点。如果可以,那么这就是你的答案。

因为我怀疑你能做到这一点,所以你要做的就是取三种不同的类型,然后使用 SFINAE 来测试它们是 Inner<>s,这就像使用基本的 is_a 元函数一样简单:

template < typename T > is_inner : boost::mpl::false_ {};
template < typename ... Pack > is_inner< Inner<Pack...> > : boost::mpl::true_ {};
于 2010-12-10T22:23:41.533 回答
1

好吧,我并没有打算回答我自己的问题,但我认为过去几天我已经把头撞到了墙上,足以解决这个问题......并且当然在此过程中学到了一些新东西(那里没有投诉)。这有点像丑小鸭(SFINAE + 类型特征元函数 + 可变参数函数模板),但我已经运行了一些简单的测试,它似乎按预期工作。

//Use SFINAE to limit the types accepted
template<typename A, typename Result>
struct require_1_type { };

//Limit to Outer class
template<typename... ArgsA, typename Result>
struct require_1_type<Outer<ArgsA...>, Result> {
    typedef Result type;
};

//Zero argument, base case for variadic function template.
void mystery_func() {}

//Recursive portion of variadic function template.
template<template<typename...> class First, typename... ArgsA, typename... Others>
typename std::enable_if<
    std::is_same<
        First<ArgsA...>
        , typename require_1_type<
            typename First<ArgsA...>::outer_t
            , typename First<ArgsA...>::outer_t::template Inner<ArgsA...>
        >::type
    >::value
    , some_lib::list<First<ArgsA...>, Others...>
>::type
mystery_func (First<ArgsA...> first, Others... others) {
    mystery_func(others...);
    return some_lib::make_list(first, others...);
}

我的目标是将传入的类型限制为 Inner 的任何变体,以及 Outer 的任何变体。我认为这可以满足我的要求,至少看起来是这样。

我对这一切如何运作的理解如下,请酌情更正:

一系列Inner对象被传入。每个Inner对象都有一个 typedef 引用其Outer类型。我们从参数包中剥离一个Inner对象,并检查引用其Outer类型的 typedef 以确保它与预期的Outer类型匹配。如果匹配,那么我们获取Inner传入的第一个对象上使用的参数包,并将包传递给我们通过first 引用的 typedef引用的Inner模板。然后我们检查这两者的相互对照,以确保它们是相同的。如果是,则启用该特定功能模板实例化。OuterInnerInner

可变参数函数模板本身只是递归地调用自己,以便参数包中的所有对象都对它们运行相同的检查,直到我们用完参数,这会调用函数的空白版本。最后,每次递归都会调用(在这种情况下)一个将对象放在一个列表中的函数。

我不确定的一件事是编译器是否正在优化所有对 make_list 的调用,这些调用返回虚无,除了最后一个调用,它是由第一次调用完成的mystery_func(),并且唯一一个有目的的返回值.

无论如何,最欢迎改进、评论和简化。

于 2010-12-14T21:47:47.240 回答