Как можно использовать 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 61

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 здесь кажется излишним.

библиотека Pythy который пытается эмулировать этот синтаксис. Однако он будет работать только на clang. Он не работает на gcc из-за этих ошибок здесь и здесь. Они могут быть исправлены для gcc 4.9, но если вы используете gcc 4.9, вы можете использовать типы автоматического возврата.