C++ 可变/不可变lambda的编译时开关

C++ 可变/不可变lambda的编译时开关,c++,lambda,c++14,C++,Lambda,C++14,我正在编写一个类成员函数,该函数将在函数参数中采用给定类型T的lambda。我的问题是:基于参数的易变性,是否有可能在编译时重载成员函数?下面是一个例子: // 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&

我正在编写一个类成员函数,该函数将在函数参数中采用给定类型
T
的lambda。我的问题是:基于参数的易变性,是否有可能在编译时重载成员函数?下面是一个例子:

// 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);
  }   
};
对于常量参数,应调用第二个参数

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

如果您计划仅使用非捕获lambda,则可以依赖这样一个事实,即它们会衰减为指向函数的指针。
下面是一个简单的工作示例:

#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 &){});
}
#包括
#包括
模板
类包装器{
T_T,;
公众:
自动运算符(){

std::cout Mmm。这似乎很好。但是,如何使用给定lambda的返回类型重载此操作?给定的f可能有自己的返回类型,而不仅仅是void。@Jes已更新。返回类型现在已推导出来。谢谢!让我消化一下。添加常量是良性的,应该使用
静态\u cast
而不是
常量cast
(如
reinterpret\u cast
,使用时应格外小心)。@skypjack:这种用法是安全的,但一般来说
const\u cast
会导致UB,因此不应在可以使用
static\u cast
的地方使用它。
const\u cast
是/应该是指示危险代码的红旗;添加const并不危险。
#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 &){});
}