получить тип конкатенированного кортежа; объединить result_of и tuple_cat

я хочу вернуть результат std::tuple_cat из моей функции, но я не могу вывести тип возвращаемого значения

#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;
}

я пытался объединить std::result_of и std::tuple_cat вот так

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

но только сообщения об ошибках

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'

вопрос: что мне поставить вместо вопросительных знаков, чтобы это работало

бонус q: почему это работает

EDIT забыл упомянуть, что мне нужен такой способ, которым я могу поместить результирующий тип в typedef, что приведет к чему-то вроде

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

Спасибо :)


person Valerij    schedule 25.08.2013    source источник


Ответы (1)


В С++ 11 вы можете использовать decltype следующим образом:

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));
}

В рабочем проекте C++1y вы можете удалить decltype следующим образом:

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));
}

А вот как вы можете получить возвращаемый тип func и поместить его в typedef, независимо от того, как закодирован возвращаемый тип func:

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>() — это просто способ получить выражение rvalue типа T без необходимости создавать его по умолчанию, например T(). Вы можете не захотеть предполагать, что T является конструктивным по умолчанию. Вы также можете получить lvalue-выражение T с declval<T&>() или константное lvalue-выражение с declval<const T&>() и т. д.

person Howard Hinnant    schedule 25.08.2013
comment
спасибо, но я не могу использовать такой decltype в typedef, как это сделать? - person Valerij; 25.08.2013
comment
Я не совсем понимаю ваш комментарий. Вы хотите сказать, что ваш компилятор не поддерживает decltype и вам нужен обходной путь? - person Howard Hinnant; 25.08.2013
comment
в конечном итоге func является функцией-членом, и я хочу указать ее возвращаемый тип через typedef, проверьте обновленный вопрос, извините - person Valerij; 25.08.2013
comment
хорошо, я заменил func на std::tuple_cat, и он работает так, как я хотел, большое спасибо (примечание для себя: загляните в declval еще раз) - person Valerij; 25.08.2013