简体   繁体   中英

Return a variadic template of tuple

I would like to create a std::tuple from elements in a std::vector and return it from my function. The size of a std::vector will not always be three so I need a function that can create a std::tuple from three, four and more elements and return it.

#include <iostream>
#include <tuple>
#include <vector>

template<typename... Args>
std::tuple<Args...> create_tuple(const std::vector<int>& vec) {
    if (vec.size() == 2)
        return std::make_tuple(vec[0], vec[1]);
    else if (vec.size() == 3)
        return std::make_tuple(vec[0], vec[1], vec[2]);
}

int main() {
    std::vector<int> vec{ 0, 1, 2 };
    auto t = create_tuple(vec);
}

Currently there is a compilation error, so how can I fix it? I am using C++11 and I cannot use ' auto ' as a value type returned from the function.

I would like to create a tuple from elements in vector and return it from my function. The size of a vector will not always be three so I need a function that can create a tuple from three, four and more elements and return it.

Short answer: you can't.

Long answer.

As explained by LogicStuff in a comment, C++ is a statically typed language.

This mean, in your case, that the compiler must known compile time the type returned by create_tuple() .

Given that the returned type depends from the size() of the argument, that is known run-time, the compiler can't choose, compile time, the correct return statement so can't choose the correct returned type.

In other words, the critical point is the body of the function

if (vec.size() == 2)
    return std::make_tuple(vec[0], vec[1]);
else if (vec.size() == 3)
    return std::make_tuple(vec[0], vec[1], vec[2]);

En passant: if vec.size() is different from 2 or 3 ( 1 by example), the compiler don't know what return. But this is a little problem compared to the fact that std::make_tuple(vec[0], vec[1]) and std::make_tuple(vec[0], vec[1], vec[2]) gives different and incompatible types.

So the compiler can't choose if the function return a std::tuple<int, int> or a std::tuple<int, int, int> .

This sort of problem can partially solved starting from C++17, with if constexpr

if constexpr (vec.size() == 2)
    return std::make_tuple(vec[0], vec[1]);
else constexpr if (vec.size() == 3)
    return std::make_tuple(vec[0], vec[1], vec[2]);
else // ???

but also if constexpr doesn't works because if constexpr require a test that must be decided compile time and with vec.size() (where vec is a std::vector ) is impossible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM