Boost如何用于实现C++ 14风格的自动返回类型?

qua*_*ant 61 c++ boost c++11

假设我有一个将两个值相加的函数.如果我对类型一无所知,那么我基本上必须写两次函数; 一次在实际返回值中,再次作为返回类型说明符:

template <typename A, typename B>
auto Add(const A& a, const B& b) ->std::decay<decltype(a + b)>::type
{
  return a + b;
}
Run Code Online (Sandbox Code Playgroud)

虽然这有效,但它是不可取的,因为它难以阅读且难以维护.

在C++ 14中,这不会是一个问题,因为我们可以删除返回类型说明符(我不确定它会不会衰减...).现在,我坚持使用C++ 11.

根据我的经验,无论何时我在C++中寻找尚未进入标准的功能,但有明显的需求,Boost库通常都有一个解决方案.我搜索了文档,但是我找不到任何可能对我有帮助的东西.这些BOOST_AUTO_RETURNBOOST_TYPEOF_TPL功能似乎更多旨在为C++ 03用户提供C++ 11功能.

基本上我所追求的是执行以下功能的东西:

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
}
Run Code Online (Sandbox Code Playgroud)

Boost库中是否有一些我不知道的功能(或C++ 11中的一个漂亮的技巧)可能允许我-> decltype(...)在每次自动返回类型后放弃显式?这将如何实施?

小智 26

C++ 11中唯一可能的推导函数返回类型是lambda的返回类型.但是,C++ 11限制了lambdas的使用.这有效:

auto add = [](int a, int b) { return a + b; };
Run Code Online (Sandbox Code Playgroud)

这是有效的,并定义add为定义operator()返回的成员函数的lambda int.由于lambda没有捕获任何东西,你甚至可以写

auto add = +[](int a, int b) { return a + b; };
Run Code Online (Sandbox Code Playgroud)

制作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
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

或者Marc Glisse指出的变种,

#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)
Run Code Online (Sandbox Code Playgroud)

看起来有点干净.

我不知道Boost中可能有类似的东西.无论如何,考虑到琐事,Boost在这里似乎有些过分.

  • @bamboon Boost非常有用,但除非在最近的版本中有所改变,否则它会出现版本问题,其中将多个项目链接在一起,这些项目全部引入Boost,并且不使用相同的版本,导致大问题,以及Boost不向后兼容的地方足以相信编译所有具有相同版本的项目不会破坏任何项目.所以,如果我没有充分的理由,我会犹豫是否使用Boost. (3认同)

Pau*_* II 5

有一个库Pythy尝试模拟这种语法.但是,它只适用于铿锵声.它不会对GCC由于这些bug的工作在这里这里.对于gcc 4.9,它们可能是固定的,但如果使用gcc 4.9,则无论如何都可以使用自动返回类型.