Time switch for mutable / immutable lambda

I am writing a member function of a class that will accept a lambda with the given type Tin the function argument. My question is: is it possible to overload a member function at compile time based on variability of the argument? The following is an example:

// T is a given type for class.
template <typename T>
class Wrapper {

  T _t;      

  // For T&
  template <typename F, typename R = std::result_of_t<F(T&)>>
  std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) {
    f(_t);
  }

  // For const T&
  template <typename F, typename R = std::result_of_t<F(const T&)>>
  std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) const {
    f(_t);
  }   
};

So, I want, if you give lambda with the following signature, I need to call the first statement.

[](T&) {
    ...  
};

For a constant argument, you need to call the second.

[](const T&) {
}
+4
source share
1 answer

If you plan on using non-exciting lambdas, you can rely on them to break down into function pointers.
This follows a minimal working example:

#include<type_traits>
#include<iostream>

template <typename T>
class Wrapper {
    T _t;      

public:
    auto operator()(void(*f)(T &)) {
        std::cout << "T &" << std::endl;
        return f(_t);
    }

    auto operator()(void(*f)(const T &)) const {
        std::cout << "const T &" << std::endl;
        return f(_t);
    }
};

int main() {
    Wrapper<int> w;
    w([](int &){});
    w([](const int &){});
}

:

#include<type_traits>
#include<iostream>
#include<utility>

template <typename T>
class Wrapper {
    T _t;      

    template<typename F>
    auto operator()(int, F &&f)
    -> decltype(std::forward<F>(f)(const_cast<const T &>(_t))) const {
        std::cout << "const T &" << std::endl;
        return std::forward<F>(f)(_t);
    }

    template<typename F>
    auto operator()(char, F &&f) {
        std::cout << "T &" << std::endl;
        return std::forward<F>(f)(_t);
    }

public:
    template<typename F>
    auto operator()(F &&f) {
        return (*this)(0, std::forward<F>(f));
    }
};

int main() {
    Wrapper<int> w;
    w([](int &){});
    w([](const int &){});
}
+1

Source: https://habr.com/ru/post/1661306/


All Articles