- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我经常使用 boost.lambda(和 phoenix)在 C++ 中定义 lambda 函数。我真的很喜欢它们的多态性、它们表示的简单性以及它们使 C++ 中的函数式编程变得如此容易的方式。在某些情况下,使用它们来定义小函数并在静态范围内命名它们甚至更清晰、更具可读性(如果您习惯阅读它们)。
存储这些最类似于常规函数的函数的方法是将它们捕获在 boost::function
const boost::function<double(double,double)> add = _1+_2;
但问题是这样做的运行时效率低下。尽管此处的 add
函数是无状态的,但返回的 lambda 类型不为空并且其 sizeof
大于 1(因此 boost::function
default ctor 和 copy ctor 将涉及 new
)。我真的怀疑编译器或 boost 端是否有一种机制来检测这种无状态并生成等同于使用的代码:
double (* const add)(double,double) = _1+_2; //not valid right now
当然可以使用 c++11 auto
,但是变量不能在非模板上下文中传递。我终于设法做到了几乎我想做的,使用以下方法:
#include <boost/lambda/lambda.hpp>
using namespace boost::lambda;
#include <boost/type_traits.hpp>
#include <boost/utility/result_of.hpp>
using namespace boost;
template <class T>
struct static_lambda {
static const T* const t;
// Define a static function that calls the functional t
template <class arg1type, class arg2type>
static typename result_of<T(arg1type,arg2type)>::type
apply(arg1type arg1,arg2type arg2){
return (*t)(arg1,arg2);
}
// The conversion operator
template<class func_type>
operator func_type*() {
typedef typename function_traits<func_type>::arg1_type arg1type;
typedef typename function_traits<func_type>::arg2_type arg2type;
return &static_lambda<T>::apply<arg1type,arg2type>;
}
};
template <class T>
const T* const static_lambda<T>::t = 0;
template <class T>
static_lambda<T> make_static(T t) {return static_lambda<T>();}
#include <iostream>
#include <cstdio>
int main() {
int c=5;
int (*add) (int,int) = make_static(_1+_2);
// We can even define arrays with the following syntax
double (*const func_array[])(double,double) = {make_static(_1+_2),make_static(_1*_2*ref(c))};
std::cout<<func_array[0](10,15)<<"\n";
std::fflush(stdout);
std::cout<<func_array[1](10,15); // should cause segmentation fault since func_array[1] has state
}
使用 gcc 4.6.1 编译该程序的输出是(无论优化级别如何):
25
Segmentation fault
如预期。在这里,我保留了一个指向 lambda 表达式类型的静态指针(出于优化目的尽可能保持常量)并将其初始化为 NULL
。这样,如果您尝试使用状态“静态化”lambda 表达式,您肯定会遇到运行时错误。如果您静态化一个真正无状态的 lambda 表达式,一切都会顺利进行。
关于问题:
该方法似乎有点脏,您能想到任何情况或编译器假设会导致这种行为不当(预期行为:如果 lambda 是无状态的,则工作正常,否则会出现段错误)。
当 lambda 表达式有状态时,您能想出任何方法来尝试此操作会导致编译器错误而不是段错误吗?
在 Eric Niebler 的回答后编辑:
#include <boost/phoenix.hpp>
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
#include <boost/type_traits.hpp>
#include <boost/utility/result_of.hpp>
using boost::function_traits;
template <class T>
struct static_lambda {
static const T t;
// A static function that simply applies t
template <class arg1type, class arg2type>
static typename boost::result_of<T(arg1type,arg2type)>::type
apply(arg1type arg1,arg2type arg2){
return t(arg1,arg2);
}
// Conversion to a function pointer
template<class func_type>
operator func_type*() {
typedef typename function_traits<func_type>::arg1_type arg1type;
typedef typename function_traits<func_type>::arg2_type arg2type;
return &static_lambda<T>::apply<arg1type,arg2type>;
}
};
template <class T>
const T static_lambda<T>::t; // Default initialize the functional
template <class T>
static_lambda<T> make_static(T t) {return static_lambda<T>();}
#include <iostream>
#include <cstdio>
int main() {
int (*add) (int,int) = make_static(_1+_2);
std::cout<<add(10,15)<<"\n";
int c=5;
// int (*add_with_ref) (int,int) = make_static(_1+_2+ref(c)); causes compiler error as desired
}
最佳答案
您说您喜欢 Boost 的 lambda 函数的多态性,但您没有在上面的代码中使用该属性。我的建议:使用 C++11 lambda。无状态的已经隐式转换为原始函数指针。这正是您正在寻找的,IMO。
===UPDATE===
虽然通过空指针调用成员函数是一个糟糕的主意(不要这样做,你会瞎的),你可以默认构造一个NEW 与原始类型相同的 lambda 对象。如果您将其与我在上面 #2 中的建议结合起来,您就可以得到想要的东西。这是代码:
#include <iostream>
#include <type_traits>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/phoenix.hpp>
namespace detail
{
using namespace boost::proto;
namespace mpl = boost::mpl;
struct is_stateless
: or_<
when<terminal<_>, std::is_empty<_value>()>,
otherwise<
fold<_, mpl::true_(), mpl::and_<_state, is_stateless>()>
>
>
{};
template<typename Lambda>
struct static_lambda
{
template<typename Sig>
struct impl;
template<typename Ret, typename Arg0, typename Arg1>
struct impl<Ret(Arg0, Arg1)>
{
static Ret apply(Arg0 arg0, Arg1 arg1)
{
return Lambda()(arg0, arg1);
}
};
template<typename Fun>
operator Fun*() const
{
return &impl<Fun>::apply;
}
};
template<typename Lambda>
inline static_lambda<Lambda> make_static(Lambda const &l)
{
static_assert(
boost::result_of<is_stateless(Lambda)>::type::value,
"Lambda is not stateless"
);
return static_lambda<Lambda>();
}
}
using detail::make_static;
int main()
{
using namespace boost::phoenix;
using namespace placeholders;
int c=5;
int (*add)(int,int) = make_static(_1+_2);
// We can even define arrays with the following syntax
static double (*const func_array[])(double,double) =
{
make_static(_1+_2),
make_static(_1*_2)
};
std::cout << func_array[0](10,15) << "\n";
std::cout << func_array[1](10,15);
// If you try to create a stateless lambda from a lambda
// with state, you trigger a static assertion:
int (*oops)(int,int) = make_static(_1+_2+42); // ERROR, not stateless
}
免责声明:我不是 Phoenix 的作者。我不知道是否保证所有无状态 lambda 的默认可构造性。
使用 MSVC-10.0 测试。
尽情享受吧!
关于c++ - 来自 boost.lambda 或 boost.phoenix 的静态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10144948/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 5 年前。 Improve
在 C# 静态方法中是否有一种方法可以引用定义该方法的类型? 在实例方法中,您可以通过以下方式确定类型: public void Foo() { Type type = this.GetTyp
WPF:静态、动态资源以及资源词典 静态资源与动态资源 我们常常会使用样式或者控件模板放在Window.Resources中,比如这样: 静态资源与动态资源使用如下: <Window
任何人都知道如何在共享/静态函数中动态加载控件?该函数本身位于 mustinherit/abstract 类中。 (这是 VB 中的 ASP.NET 项目)我想做这样的事情: VB: Publ
在我看来,静态/强类型编程语言最宝贵的一点是它有助于重构:如果/当您更改任何 API,那么编译器会告诉您该更改破坏了什么。 我可以想象用运行时/弱类型语言编写代码......但我无法想象没有编译器的帮
正如我的名字所暗示的,我是一名 .NET 开发人员,但我对 Java 的兴趣越来越大,并且我有兴趣学习更多其他语言,因为这有助于我学习更多关于编程的知识。 无论如何,我的问题是:不带参数/不使用状态的
我在java中使用WireMock来 stub POST请求。该请求返回一个存储在我本地的 json 正文文件。 stub 看起来像这样: wireMockServer.stubFor(get(url
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
这个问题已经有答案了: What is the difference between dynamic and static polymorphism in Java? (14 个回答) 已关闭 4 年
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Static initializer in Java 我想知道这个静态的东西(抱歉,这是我第一次遇到这个)对一个类有
如果c++应用程序是按以下方式组织的 //file1.cpp static Y sgObj = X::getInitObject(0); //declared in file scope //fil
我有一个抽象类(AvergedDataRecord),我需要进一步抽象(DataRecord),这样我就可以将它扩展到原始类和一个新的具体类(SummedDataRecord),并且我在获取某些方法时
我正在尝试制作一个字符串枚举。这是我到目前为止所得到的, private class TypedEnum : IEnumerable { public IEnumerator GetEnume
我选修了一门名为“安全代码”的类(class),在下一个作业中,我们应该对一些 C 文件和 JavaEE Web 项目进行静态/动态分析。 我检查了“源监视器”并在 C 文件上运行它,但是(除非我不知
我有两个类,一个是登录类,一个是用户类。在 loggedIn 类中,我想显示我在用户登录时所做的共享首选项。 loginPrefs = getSharedPreferences("loginprefe
我在同一个 Activity 中有两个静态 fragment ,在“fragmentA”中我有一个自定义列表,当一个项目被点击时必须在“fragmentB”中出现一个细节,细节只在我改变屏幕方向时出现
在 Java 中是未修改方法变量,缺少final,每次都重新初始化限定符 静态方法 实例方法 如果 1. 或 2.(或两者)的答案是 final 限定符允许 Java 执行优化并存储方法变量只有一次?
我有两个类相互交互。第一个是中心的,如下: public class Datenbank { double winkelPanel = 0; double groessePanel = 0; doub
我有一个 mysql 数据库,它连接基于 Web 的 php 应用程序和 FoxPro 应用程序(是的,foxpro)。在之前的“开发人员”被解雇后开始处理这个问题。 无论如何,我熟悉 AES_Enc
我是一名优秀的程序员,十分优秀!