Как можно использовать Boost для достижения типов автоматического возврата в стиле C++14?
Предположим, у меня есть функция, которая складывает два значения. Если я ничего не знаю о типах, то я в основном должен написать свою функцию дважды; один раз в фактическом возвращаемом значении и снова в качестве спецификатора возвращаемого типа:
template <typename A, typename B>
auto Add(const A& a, const B& b) ->std::decay<decltype(a + b)>::type
{
return a + b;
}
в то время как это работает, это нежелательно, потому что трудно читать и трудно поддерживать.
в C++14 это не будет проблемой, потому что мы можем удалить спецификатор возвращаемого типа (я не уверен, что он будет делать распад, хотя...). Пока, Я застрял с C++11.
это был мой опыт, что всякий раз, когда я ищу функцию в C++, которая еще не пробилась в стандарт, но для которой есть очевидная необходимость,библиотека обычно имеет решение. Я просмотрел документацию, но не нашел ничего, что могло бы мне помочь. Элемент BOOST_AUTO_RETURN
и BOOST_TYPEOF_TPL
функции, похоже, больше направлены на предоставление функциональности C++11 для пользователей C++03.
в основном то, что я после этого что-то, что выполняет следующие функции:
template <typename A, typename B>
auto Add(const A& a, const B& b)
{
return a + b; // Deduce return type from this, like C++14 would
}
есть ли какая-то функциональность в библиотеке Boost, о которой я не знаю (или отличный трюк в C++11), который может позволить мне отказаться от явного -> decltype(...)
после каждого типа автоматического возврата? Как это будет реализовано?
2 ответа:
единственный возможный выводимый тип возврата функции в C++11-это тип возврата лямбды. Однако C++11 ограничивает использование лямбд. Это работает:
auto add = [](int a, int b) { return a + b; };
это действительно, и определяет
add
как лямбда, которая определяетoperator()
функция-член, которая возвращаетint
. Поскольку лямбда ничего не захватывает, вы даже можете написатьauto add = +[](int a, int b) { return a + b; };
сделать
add
обычный указатель на функцию: он получает типint(*)(int, int)
.Однако, C++11 не позволяет указывать типы параметров как
auto
, ни датьadd
определяется как переменная шаблона, поэтому вы не можете использовать ее для общего вывода типа возвращаемого значения. Попытка обернуть его в класс шаблона завершается неудачей:template <typename A, typename B> struct S { static auto add = [](A a, B b) { return a + b; }; }; // invalid
инициализация недопустима
add
В-класса, и вы не можете использоватьauto
если член не инициализирован в классе. Кроме того, даже если бы это сработало, это не позволило бы вычитатьA
илиB
, который, кажется, больше того, что ты после этого.учитывая эти ограничения, я не вижу никакой альтернативы, кроме как повторять слова. Однако вы можете скрыть повторение в тривиальном макросе.
#define AUTO_RETURN(func, ...) auto func -> decltype(__VA_ARGS__) { return __VA_ARGS__; } template <typename A, typename B> AUTO_RETURN(add(A a, B b), a + b)
или вариант, на который указал Марк Глисс,
#define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } template <typename A, typename B> auto add(A a, B b) RETURNS(a + b)
, который выглядит немного чище.
там может быть что-то вроде этого в Boost уже, я не знаю. Несмотря на это, учитывая тривиальность, Boost здесь кажется излишним.