Question

i want to return the result of std::tuple_cat from my function but i fail to deduce the return type

#include <tuple>

struct H {
    typedef std::tuple<int,int> tuple_type;
    tuple_type a {1,2};
};

template <typename tuple_holder_type, typename B>
???
func(tuple_holder_type h, B b) {
    return std::tuple_cat(h.a,std::make_tuple(b));
}

int main(int argc, char const *argv[]) {
    auto h = H();
    auto b = 3;
    auto c = func(h,b);
    return 0;
}

i tried to combine std::result_of and std::tuple_cat like this

typename std::result_of<std::tuple_cat(tuple_holder_type::tuple_type,std::tuple<B>) >::type

but only got error messages

test.cpp:9:85: error: template argument 1 is invalid
test.cpp:9:86: error: expected identifier before '::' token
test.cpp:10:1: error: expected initializer before 'func'

the question: what do i put instead of the question marks for this to work

bonus q: why does it work

EDIT forgot to mention i need such a way i can put the resulting type in a typedef, resulting in something like

template <typename tuple_holder_type, typename B>
struct tuple_appender {
    typedef ??? return_type;
    return_type operator() /*...*/
}

thank you :)

Was it helpful?

Solution

In C++11 you can use decltype like this:

template <typename tuple_holder_type, typename B>
auto
func(tuple_holder_type h, B b)
    -> decltype(std::tuple_cat(h.a,std::make_tuple(b)))
{
    return std::tuple_cat(h.a,std::make_tuple(b));
}

In the C++1y working draft, you can drop the decltype like this:

template <typename tuple_holder_type, typename B>
auto
func(tuple_holder_type h, B b)
{
    return std::tuple_cat(h.a,std::make_tuple(b));
}

And here is how you can get the return type of func and put it in a typedef, no matter how func's return type is coded:

template <typename tuple_holder_type, typename B>
struct tuple_appender {
    typedef decltype(func(std::declval<typename tuple_holder_type::tuple_type>(),
                          std::declval<std::tuple<B>>())) return_type;
};

std::declval<T>() is just a way to get an rvalue expression of type T without having to default construct one, like T(). You may not want to assume that T is default constructible. You can also get an lvalue expression of T with declval<T&>(), or a const lvalue expression with declval<const T&>(), etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top