The aim is to provide a generic functor class which makes references able to bind to r-values. The trick is to trick the compiler into thinking that the r-value is an l-value by using a forwarding references. Here is the code:

#include <type_traits>
template <typename Functor>
struct Function {
    Functor func;
    template <typename ...Args>
    inline auto operator() (Args&&... args) {
        //I tried to provide a suitable error message if args were not valid parameters, but I can't get it to work...
        //static_assert(std::is_invocable_v<Functor, Args...>);
        return func(args...);

Example use case:

# include <iostream>
# include <vector>
int main () {
    // Define function 
    auto push_back = Function([] (std::vector<int>& vec, int num) {vec.push_back(num); return vec;});
    auto x = std::vector{1 , 2 ,3 , 4};
    // Works on l-values
    push_back(x, 5);
    std::cout << x[4] << '\n'; // 5
    // Works on r-values
    auto y = push_back(std::vector{1 ,2 , 3 , 4 , 5}, 6);
    std::cout << y[5] << '\n'; // 6
    return 0;

And finally, one can do this if you want to use old-style c functions:

template <typename R, typename ...Args>
inline auto CFunc(R (*iFunc) (Args...)) {
    return Function<R (*) (Args...)>(iFunc);

Is this robust code? Are there edge cases I need to be aware about with which my functor class does not work? Also, how could I provide more suitable error messages, eg when typename Functor is not a functor, or when args... are not suitable parameters?


1 Answer 1


Assuming C++20, we can constrain the template (similar to your attempt at static_assert). The key is that Args... can contain rvalue-references, but we need to convert those to lvalue types, because that's what we present to the function:

#include <concepts>
    template<typename... Args>
    inline auto operator()(Args&&... args)
        requires std::invocable<Functor, std::add_lvalue_reference_t<Args>...>

I don't see anything else I would propose improving.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.