我有一个将可索引对象作为模板参数的方法,例如:
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
有没有一种方法可以为o
参数传递一个lambda函数?换句话说,是否可以通过[]
运算符而不是()
运算符来调用lambda?
答案 0 :(得分:4)
template<class F>
struct square_bracket_invoke_t {
F f;
template<class T>
auto operator[](T&& t)const
-> typename std::result_of< F const&(T&&) >::type
{ return f(std::forward<T>(t)); }
};
template<class F>
square_bracket_invoke_t< typename std::decay<F>::type >
make_square_bracket_invoke( F&& f ) {
return {std::forward<F>(f)};
}
代码是C ++ 11,基本开销为零。
int main() {
std::cout << foo( 6, make_square_bracket_invoke([](int x){ return x; } ) ) << "\n";
}
结果是0 + 1 + 2 + 3 + 4 + 5,也就是15。
这是个好主意吗?也许。但是为什么要停在那里?
为了最大程度的娱乐:
const auto idx_is = make_square_bracket_invoke([](auto&&f){return make_square_bracket_invoke(decltype(f)(f));});
int main() {
std::cout << foo( 6, idx_is[[](int x){ return x; }] ) << "\n";
}
答案 1 :(得分:2)
您可以通过以下方式实现:
operator[]
的类模板,仿函数。operator[]
的{{1}}实施operator()
。std::function
中,作为类模板的成员变量。
这是一个演示程序。
std::function
及其输出
#include <iostream>
#include <functional>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
template <typename> struct Functor;
template <typename R> struct Functor<R(int)>
{
using ftype = std::function<R(int)>;
Functor(ftype f) : f_(f) {}
R operator[](int i) const { return f_(i); }
ftype f_;
};
int main()
{
Functor<int(int)> f = {[](int i) -> int {return i*i;}};
std::cout << foo(10, f) << std::endl;
}
285
在这里不合适。它不会使函数调用运算符过载。我怀疑还有一个更合适的名称。
答案 2 :(得分:1)
好吧,如果有帮助的话,这是一种将包装类的dest_port
转发到lambda的operator[]
的方法。
operator()
我经常使用这样的包装器。它们很方便,并且似乎没有任何计算开销,至少在由GCC编译时。您可以为template<class F>
struct SubscriptWrapper_t {
F f_;
template<class T> auto operator[](T const& t_) const -> decltype(f_(t_)) {
return f_(t_);
}
};
template<class F>
SubscriptWrapper_t<typename std::decay<F>::type> SubscriptWrapper(F&& f_) {
return{std::forward<F>(f_)};
}
做一个,甚至可以为at
做一个。
编辑:已针对C ++ 11更新(并已更新为能够返回引用)
答案 3 :(得分:0)
可以执行此操作的包装类型的草图。
template<typename UnaryFunction>
class index_wrapper
{
public:
index_wrapper(UnaryFunction func) : func(std::move(func)) {}
template<typename T>
std::invoke_result_t<UnaryFunction, T> operator[](T&& t)
{ return func(std::forward<T>(t)); }
private:
UnaryFunction func;
};
随用法
#include <iostream>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
int main()
{
index_wrapper f([](int i) -> int { return i*i; });
std::cout << foo(10, f) << std::endl;
}
您可能希望将其限制为单个参数类型,以便可以提供类似于std::vector::reference
等的成员类型别名。