限制可变参数函数模板只接受一个可变参数类模板的嵌套可变参数类模板的变体?

时间:2010-12-10 22:14:58

标签: c++ templates function c++11 variadic

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

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或可变功能模板(或其他)解决方案吗?

2 个答案:

答案 0 :(得分:2)

我认为这可能实际上是不可能的。你似乎想要的是做这样的事情的能力:

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

我认为你不能那样做。如果可以,那就是你的答案。

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

template < typename T > is_inner : boost::mpl::false_ {};
template < typename ... Pack > is_inner< Inner<Pack...> > : boost::mpl::true_ {};

答案 1 :(得分: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个对象。每个Inner对象都有一个typedef引用其“Outer类型。我们从参数包中剥离了一个Inner对象,并检查typedef引用其“Outer类型”以确保它与预期的Outer类型匹配。如果匹配,则我们获取传入的第一个Inner对象上使用的参数包,并将包传递到我们通过引用的Inner typedef引用的Outer模板到第一个Inner。然后我们互相检查这两个Inner,以确保它们是相同的。如果是,则启用该特定功能模板实例化。

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

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

无论如何,我们非常欢迎改进,评论和简化。

相关问题