2

假设我有一个正在展开的参数包,例如

template<typename... P> void f(P...&& args) {
    some_other_func(std::forward<P>(args)...);
}

现在假设我有一些其他的小功能,这些对象需要通过。

template<typename T> T&& some_func(T&& ref) {
    // replace with actual logic
    return std::forward<T>(ref);
}

我通常会替换为

template<typename... P> void f(P...&& args) {
    some_other_func(some_func(args)...);
}

但是,如果some_func需要有关参数的更多信息而不仅仅是它的类型,例如,它在参数包中的数字位置,我该怎么办?所以,而不是扩大到

some_other_func(some_func(arg1), some_func(arg2));

我可以将其扩展到

some_other_func(some_func(arg1, 1), some_func(arg2, 2));

例如?

4

2 回答 2

2

这有点令人费解。但这是一个使用libc++的几个私有实用程序的代码的工作原型,可在 <__tuple><tuple>中找到。

#include <iostream>
#include <tuple>

template<typename T>
int
some_func(T&& ref, size_t I)
{
    std::cout << "ref = " << ref << ", I = " << I << '\n';
    return 0;
}

template<typename... T, size_t ...Indx>
void
some_other_func(std::tuple<T...> ref, std::__tuple_indices<Indx...>) {
    // replace with actual logic
    std::__swallow(some_func(std::get<Indx>(ref), Indx)...);
}


template<typename... P>
void
f(P&&... args)
{
    some_other_func(std::forward_as_tuple<P...>(std::forward<P>(args)...),
                    typename std::__make_tuple_indices<sizeof...(P)>::type());
}

int main()
{
    f("zero", "one", "two", "three");
}

ref = zero, I = 0
ref = one, I = 1
ref = two, I = 2
ref = three, I = 3
于 2011-04-25T01:54:42.803 回答
2

我知道我以前解决过这个问题,但不记得是如何解决的。哦,好吧,这是一个新鲜的外观。

可以使用 将数字序列转换为参数序列std::get,因此它更基本。所以,假设我需要实现某种自定义工具,数字包生成器似乎是一个不错的选择。

(啊,这太乏味了。我确实偷看了霍华德的回答并了解了forward_as_tuple,但我的编译器或 ideone.com 上什至还不存在该功能,所以等等。还有很多事情我仍然需要弄清楚,这肯定是有史以来最糟糕的函数式语言之一。)

http://ideone.com/u5noV

#include <tuple>

// Generic pack array (metacontainer)
template< typename T, T ... seq > struct value_sequence {
    // Append a value to the array (metafunction)
    template< T val > struct append
        { typedef value_sequence< T, seq..., val > type; };
};

// Generate a sequential array (metafunction)
template< size_t N >
struct index_sequence {
    typedef typename index_sequence< N - 1 >::type
                      ::template append< N - 1 >::type type;
};

template<>
struct index_sequence< 0 >
    { typedef value_sequence< size_t > type; };

// Generate indexes up to size of given tuple (metafunction)
template< typename T >
struct index_tuple {
    typedef typename index_sequence< std::tuple_size< T >::value
                                   >::type type;
};

// The magic function: passes indexes, makes all the function calls
template< typename F, typename G,
          typename T, size_t ... N >
void compose_with_indexes_helper( F f, G g, T args,
        value_sequence< size_t, N ... > ) {
    f( g( std::get< N >( args ), N ) ... );
}

template< typename F, typename G, typename ... T >
void compose_with_indexes( F f, G g, T && ... args ) {
    typedef std::tuple< T && ... > tuple_t;
    compose_with_indexes_helper
//        forwarding seems broken on ideone.com/GCC 4.5.1, work around.
//        ( f, g, std::forward_as_tuple( std::forward( args ) ... ) );
        ( f, g, tuple_t( args ... ), typename index_tuple< tuple_t >::type() );
}
于 2011-04-26T11:01:01.733 回答