C++11:如何编写一个像 get<tuple>... 但接收参数包的模板函数?

标签 c++ c++11 templates parameters pack

我知道在 c++11 中,get<> 模板函数与 std::tuple 一起使用以获取元组的索引值,这是在编译时解决的。

但我的要求是有一个名为get<>的模板函数,但接收一个参数包,所以代码应该像下面这样:

#include<iostream>
using namespace std;
template<typename Head, typename ... Tail>
auto get(size_t index, Head&& t, Tail&&...tail){
    return get(index-1, tail...);
}
template<typename Head, typename ... Tail>
Head get<0>(Head&& t, Tail&&...tail){
    return t;
}
int main(){
    cout<<get(3,"abc",'x',27,"hello")<<endl;
    cout<<get(2,"abc",'x',28,"hello")<<endl;
    return 0;
}

当然,它无法编译,因为我不知道如何编写这样的“get”模板函数。我希望主要功能将运行并打印如下:

hello
28

所以我的问题是:如何实现我上面提到的这个“get”模板? 谢谢!

最佳答案

真的需要能够在运行时选择索引吗?如果没有,以下应该足够了:

template <std::size_t Index, typename ...P> auto get(P &&... params)
{
    return std::get<Index>(std::make_tuple(params...));
}

// ...

std::cout << get<1>("abc", 42, 123.456); // Prints 42

如果您确实希望将索引作为普通(运行时)参数,则必须返回 std::variant<P...>(或 std::any 或标记的 union ),因为返回类型不能依赖于运行时参数。

一个可能的实现可能是这样的:

template <typename ...P> std::variant<P...> get(std::size_t index, P &&... params)
{
    std::size_t pos = 0;
    std::variant<P...> ret;
    ((index == pos++ ? void(ret = params) : void()) , ...);
    return ret;
}

// ...

std::cout << std::get<int>( get(1, "abc", 42, 123.456) ); // Prints 42 too, but looks ugly

或者您可以将返回类型指定为模板参数:

template <typename T, typename ...P> T get(std::size_t index, P &&... params)
{
    std::size_t pos = 0;
    std::variant<P...> va;
    ((index == pos++ ? void(va = params) : void()) , ...);
    if (T *ptr = std::get_if<T>(va))
        return T;
    else
        throw /*something*/;
}

// ...

std::cout << get<int>(1, "abc", 42, 123.456); // 42

或者您可以将值传递给函数/仿函数:(感谢@Yakk)

template <typename T, typename ...P> void get(std::size_t index, T &&func, P &&... params)
{
    std::size_t pos = 0;
    ((index == pos++ ? void(func(params)) : void()) , ...);
}

// ...

get(1, [](int x){std::cout << x;}, "abc", 42, 123.456); // 42
// Alternative:
// get(1, [](auto x){std::cout << x;}, "abc", 42, 123.456); // 42 too, 
// but you could print any type which can be printed without having to 
// specify the type manually.

关于C++11:如何编写一个像 get<tuple>... 但接收参数包的模板函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45309787/

相关文章:

c++ - 创建一个像 std::integral_constant 这样的容器

c++ - 尝试在 cygwin : error: expected unqualified-id before '&&' token 中构建 boost 文件系统时出错

c++ - 在可移动类的构造函数中初始化 std::thread

c++ - vector 中的移动元素未按预期工作

c++ - 如何在 VS2015 的监 window 口中查看 C++ 模板参数

c++ - 链表 - 覆盖数据

c++ - FD_READ : recv() returning two packets at once

c++ - 解析两种格式的文件并解析行

c++ - move 是否会使对象处于可用状态?

c++ - 如何静态检查模板的类型 T 是否为 std::vector<U>,其中 U 为 float、double 或 integral