Best way to avoid code huge duplication when deducing return type using decltype

StackOverflow https://stackoverflow.com/questions/19129675

  •  30-06-2022
  •  | 
  •  

Вопрос

I have this very convoluted example here:

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

I have a bunch of similar factory functions for constructing SomeClass with various different functors.

Using the above technique with no trailing return type works just nicely compiling with -std=c++1y on gcc 4.8, but I'm not keen on using c++1y features just yet, nor am I keen on using an enormous, code duplicating decltype for trailing return type.

What other options are there for deducing the lambda for use in the return type?

I've considered using std::function, but would prefer to avoid using that in this case.

Это было полезно?

Решение

Replace lambda with an explicit functor.

Alternatively, create a make_class function that perfect forwards the lambda and deduces its type into a some_class constructor, relying on RVO to elide any copies or use {direct construction} to explicitly construct the return value, and maybe a RETURNS macro:

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

… which does not work now that I think about it, as we get a lambda in a non evaluated context.

Другие советы

Generally speaking, the only ways to combat template-induced code bloat is to either factor template-independent code out, erase the type, or a hybrid of the two.

As for factoring template-independent code, if Arg1, and SomeArg are not template parameters, you can completely factor the lambda out in the form of a free standing function. If they are template parameters, you might still be able to factor parts of the template-independent logic out of the lambda, and minimize the bloat.

As for type erasure, you can either resort to a) virtual base classes coupled with derived template classes (which is actually what std::function uses under the hood), b) use C-style void (*)( void * ) function pointers, or rely on c) non-standard hacks such as this one: Member Function Pointers and the Fastest Possible C++ Delegates.

You are treading the dusty corners of the language here. Word of advice: save yourself a world of hurt, and keep it simple.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top