我正在尝试在Boost.Proto中创建一个匹配矢量类型的语法,但是当我给它一个该类型的终端时,它与语法不匹配.类型定义如下所示:
template <typename T, unsigned D>
struct vector
{
typedef T scalar;
enum { size = D };
scalar& operator[](unsigned i)
{
return m_components[i];
}
scalar const& operator[](unsigned i) const
{
return m_components[i];
}
private:
scalar m_components[size];
};
Run Code Online (Sandbox Code Playgroud)
我试图匹配的语法看起来像这样:
namespace proto = boost::proto;
using proto::_;
using proto::N;
struct test:
proto::terminal<vector<_, N> >
{};
Run Code Online (Sandbox Code Playgroud)
比赛失败:
int main ()
{
BOOST_MPL_ASSERT((proto::matches<proto::terminal<vector<float, 2> >::type, test>));
}
Run Code Online (Sandbox Code Playgroud)
如何制作与特定类型匹配的语法?
编辑:
似乎proto :: _和proto :: N在自定义类型中不用作通配符.代码用这个语法编译(matches
断言传递):
struct test:
proto::terminal<vector<float, 2> >
{};
Run Code Online (Sandbox Code Playgroud)
但是当其中任何一个通配符属于该类型时,它都不起作用:
struct …
Run Code Online (Sandbox Code Playgroud) 我经常使用boost.lambda(和phoenix)在C++中定义lambda函数.我非常喜欢它们的多态属性,它们表示的简单性以及它们在C++中进行函数式编程的方式变得如此简单.在某些情况下,它甚至更清晰,更易读(如果您习惯于阅读它们),可以使用它们来定义小函数并在静态范围内命名它们.
存储这些类似于传统功能的功能的方法最多的是捕获它们 boost::function
const boost::function<double(double,double)> add = _1+_2;
Run Code Online (Sandbox Code Playgroud)
但问题是这样做的运行时效率低下.即使add
这里的函数是无状态的,返回的lambda类型也不是空的并且它sizeof
大于1(因此boost::function
默认的ctor和copy ctor将涉及new
).我真的怀疑编译器或boost方面有一种机制来检测这种无状态并生成相当于使用的代码:
double (* const add)(double,double) = _1+_2; //not valid right now
Run Code Online (Sandbox Code Playgroud)
当然可以使用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);
} …
Run Code Online (Sandbox Code Playgroud) 我想通过编写一个由函数指针模板化的原型转换来重用代码:
template <typename Ret, typename A0, typename A1, Ret func(A0,A1)>
struct apply_func : proto::callable
{
// Do something with func
};
Run Code Online (Sandbox Code Playgroud)
但是,函数本身是多态的,所以我不想指定它的确切签名.
我希望我的代码看起来像的简化版本(我使用外部转换的技术原因,我认为与我当前的问题无关 - 如果没有它们,我无法使递归工作):
template<typename R, typename A0, typename A1>
R plus_func(A0 lhs, A1 rhs) { return lhs+rhs; }
template<typename R, typename A0, typename A1>
R minus_func(A0 lhs, A1 rhs) { return lhs-rhs; }
struct my_grammar;
struct plus_rule : proto::plus<my_grammar, my_grammar> {};
struct minus_rule : proto::minus<my_grammar, my_grammar> {};
struct my_grammar
: proto::or_<
proto::when<proto::terminal<proto::_>, proto::_value>
, proto::when<plus_rule, proto::external_transform >
, …
Run Code Online (Sandbox Code Playgroud) 我想使用Boost.Proto将嵌入式领域特定语言转换为使用Eigen库实现的一系列矩阵运算.由于效率很重要,我希望proto生成特征表达模板并避免过早评估.
我已经实现了一个可以生成矩阵乘法表达式的简单语法.下面的代码编译时没有警告(在g ++ 4.8.0和Intel C++ 2013.3上,Boost 1.54.0和Eigen 3.1.3)并且只要我的表达式只有一个乘法运算就可以工作.一旦我向链中添加更多乘法,它就会崩溃.Valgrind告诉我,这是因为在评估完成之前,其中一个Eigen :: GeneralProduct表达式模板临时值被销毁.
我不明白为什么会这样,或者我能做些什么来阻止它.所有帮助表示赞赏!
#include <iostream>
#include <boost/fusion/container.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/void.hpp>
#include <boost/proto/proto.hpp>
#include <boost/ref.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility.hpp>
#include <Eigen/Dense>
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
namespace proto = boost::proto;
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> matrix;
// Placeholders
const proto::terminal<mpl::int_<0> >::type I1 = {{}};
const proto::terminal<mpl::int_<1> >::type I2 = {{}};
const proto::terminal<mpl::int_<2> >::type I3 = {{}};
// Grammar
template<class Rule, class Callable = proto::callable>
struct External :
proto::when<Rule, …
Run Code Online (Sandbox Code Playgroud) 背景问题:boost.proto +在构建表达式树之前检测无效终端.
嗨,我想要实现的是
所以,对于1.我最终得到了这个代码
///////////////////////////////////////////////////////////////////////////////
// A transform that converts all vectors nodes in a tree to iterator nodes
struct vector_begin : proto::transform <vector_begin>
{
template<typename Expr, typename Unused1, typename Unused2>
struct impl : boost::proto::transform_impl<Expr, Unused1, Unused2>
{
// must strip away the reference qualifier (&)
typedef typename proto::result_of::value<
typename boost::remove_reference<Expr>::type
>::type vector_type;
typedef typename proto::result_of::as_expr
<typename vector_type::const_iterator>::type result_type;
result_type operator ()(
typename impl::expr_param var
, typename impl::state_param
, typename impl::data_param) const
{
typename vector_type::const_iterator …
Run Code Online (Sandbox Code Playgroud) 我正在尝试原型和凤凰,我的第一个玩具示例是什么崩溃,我不知道我应该在哪里看.由于#boost IRC频道上的某个人告诉我要确保首先对凤凰表达树进行深度复制(以便x
在构建时没有悬空引用),我将表达式包裹起来boost::proto::deep_copy
.然而,这并没有奏效.使用-O2
标志编译时仍然崩溃,省略时工作正常.
#include <boost/phoenix/phoenix.hpp>
#include <boost/proto/deep_copy.hpp>
#include <iostream>
namespace bpr = boost::proto;
int main(int argc, char **argv) {
using namespace boost::phoenix;
using namespace placeholders;
auto x = bpr::deep_copy(
switch_(arg1)[
case_<1>(std::cout << val("hello")),
case_<2>(std::cout << val("bye")),
default_(std::cout << val("default"))
]);
x(1);
x(2);
}
Run Code Online (Sandbox Code Playgroud)
我希望这能输出hellobye
.
在Boost Phoenix文章中,"转换表达式树",这里是一组自定义invert_actions
类的特化,用于反转二进制算术表达式.例如a+b
变成a-b
; a*b
变得a/b
; 反之亦然.
这涉及表达式树的递归遍历 - 但是,当遇到涉及未明确处理的运算符的表达式时,此遍历将停止.例如,_1+_2-_3
将成为_1-_2+_3
,但_1+_1&_2
将保持原样(没有处理程序&
).let(_a = 1, _b = 2) [ _a+_b ]
也将保持不变.
我曾经认为这是本文所预期的,但看看最后列出的测试,我看到if_(_1 * _4)[_2 - _3]
预计会发生变化; 使用提供的代码(这里),我发现它没有.
那么如何定义一个通用的Boost Phoenix表达式树变换,它适用于所有一组明确列出的(n-ary)运算符; 让其他人保持不变?
某些代码可能很有用.我想要输出以下C++ 11代码(auto)0
,而不是2
; 没有显式处理&
或任何其他运算符/语句.
#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/proto/proto.hpp>
using namespace boost;
using namespace proto;
using namespace phoenix;
using namespace arg_names;
struct …
Run Code Online (Sandbox Code Playgroud) 如何在Boost Phoenix表达式的转换中包含函数体?
例如,我构建了Boost Phoenix Starter Kit的Lazy Functions部分,并创建了一个延迟添加函数:
struct my_lazy_add_impl {
typedef int result_type;
template <typename T>
T operator()(T x, T y) const { return x+y; }
};
phoenix::function<my_lazy_add_impl> my_add;
Run Code Online (Sandbox Code Playgroud)
然后,我从前一个问题准备一个简单的加号 - 减号变换,如下所示:
struct invrt:
proto::or_<
proto::when<
proto::plus<proto::_, proto::_>,
proto::functional::make_expr<proto::tag::minus>(
invrt(proto::_left), invrt(proto::_right)
)
>,
proto::otherwise<
proto::nary_expr<proto::_, proto::vararg<invrt> >
>
>
{};
Run Code Online (Sandbox Code Playgroud)
但是,当我应用倒置凤凰lambda
表达式时,my_add
如下所示使用其参数,似乎尚未实现预期的反转.是否有推荐的方法在Phoenix中实现函数调用,这可以促进这种转换?
int main(int argc, char *argv[])
{
auto f = phoenix::lambda(_a = 0)[my_add(_1,_2)];
auto g = invrt()(phoenix::lambda(_a = 0)[my_add(_1,_2)]);
std::cout << f()(1,2) …
Run Code Online (Sandbox Code Playgroud) 我可以将Boost Phoenix表达式转换为代表性的C++字符串吗?我本可以有:
stringify(_1<_2);
Run Code Online (Sandbox Code Playgroud)
然后可能会生成一个包含以下内容的字符串:
template <class T1, class T2>
struct foo {
auto operator()(T1 x1, T2 x2)
-> decltype(x1 < x2)
{ return x1 < x2; }
};
Run Code Online (Sandbox Code Playgroud)
我很欣赏这个例子有一些粗糙的边缘,但我想知道这些线路是否有任何尝试?
我有一个foo()
在库上下文中提供的函数.该库为此函数定义了一些重载,如:
char foo(float x, int y);
short foo(double x, char y);
Run Code Online (Sandbox Code Playgroud)
(我做了上面的参数/结果类型.要点是参数类型和重载的相应返回类型之间没有通用关系.)
这个想法是库用户可以foo()
根据需要为他们自己的用户定义类型添加重载.函数重载非常容易实现.
我想foo()
在Boost.Proto表达式中使函数族可用.为了做到这一点,我想我需要使用模板调用操作符将上面的内容包装在一个函数对象中:
struct foo_wrap
{
template <typename A1, typename A2>
result_type operator()(A1 a1, A2 a2) { return foo(a1, a2); }
};
Run Code Online (Sandbox Code Playgroud)
问题在于如何定义result_type
.我意识到使用C++ 11和decltype()
尾随函数返回类型会很容易,但我正在寻找一个C++ 03解决方案.因此,foo_wrap
需要成为TR1风格的函数对象.我需要找到一种方式来定义result_type
的参数类型的编译时的功能A1
和A2
.这不仅需要返回类型operator()
,还需要TR1 result_of
协议.简而言之: