使用decltype推断返回类型时避免代码大量重复的最佳方法

时间:2013-10-02 03:47:49

标签: c++ templates decltype

我在这里有一个非常复杂的例子:

auto someClassFactory(const Arg1& arg1, const Arg2& arg2, const Arg3)
{
    auto lambda = [arg1](const SomeArg& a) {
        // 10 or so line lambda...
        // ...
        // ...
    };

    return SomeClass<decltype(lambda)>{arg2, arg3, lambda};
}

我有一堆类似的工厂函数,用于构造具有各种不同函子的SomeClass。

gcc 4.8 上使用没有尾随返回类型的上述技术可以很好地编译 -std = c ++ 1y ,但我并不热衷于使用 c ++ 1y 功能,我也不热衷于使用巨大的代码重复decltype作为尾随返回类型。

还有哪些其他选项可以推断出lambda用于返回类型?

我考虑过使用std::function,但在这种情况下我宁愿避免使用它。

2 个答案:

答案 0 :(得分:2)

用显式仿函数替换lambda。

或者,创建一个make_class函数,该函数完美转发lambda并将其类型推导为some_class构造函数,依赖于RVO来删除任何副本或使用{direct construction}显式构造返回值,也许是RETURNS宏:

#define RETURNS(x) ->decltype(x) { return (x); }

...现在我考虑不起,因为我们在非评估的上下文中得到一个lambda。

答案 1 :(得分:1)

一般来说,打击模板引发的代码膨胀的唯一方法是将与模板无关的代码输出,擦除类型或两者的混合。

对于分解与模板无关的代码,如果Arg1和SomeArg不是模板参数,则可以以独立函数的形式完全分解lambda。如果它们是模板参数,您可能仍然可以将与模板无关的逻辑部分从lambda中分解出来,并最小化膨胀。

对于类型擦除,你可以求助于a)与派生模板类相结合的虚拟基类(实际上是std :: function在引擎盖下使用的),b)使用C风格的void(*)(void *)函数指针,或依赖于c)非标准的黑客攻击:Member Function Pointers and the Fastest Possible C++ Delegates

你正在这里踩着语言的尘土飞扬的角落。建议:为自己保护一个受伤的世界,并保持简单。