我正在試驗原始構建一個DSEL,它在幾何向量上運行。我正在嘗試編寫一個轉換,它將採用賦值表達式並將其展開爲明智的組件。舉例來說,我想Boost.Proto和複雜轉換
p[0] = q[0] + r[0],
p[1] = q[1] + r[1],
...,
p[N] = q[N] + r[N],
p;
到目前爲止,我已經能夠更換
p = q + r;
大多使其通過進行轉換模板unroll_vector_expr
是遞歸解開表達對每個矢量分量工作結合distribute_subscript
變換。
我似乎不明白什麼是與boost::result_of
和result_of::make_expr
使用的'參數'的基本原理。文檔,示例和內部代碼似乎混合使用Expr
,impl::expr
和impl::expr_param
。我不確定我應該使用什麼以及何時使result_type
與實際結果類型相匹配。目前,通過檢查錯誤消息並修復const
和&
的差異,我通過嘗試發現了一個錯誤。但是,一旦我深度複製表達式,終端將不再被引用,我的代碼將失敗。
struct distribute_subscript
: or_<
scalar_grammar
, when<
vector_literal
, _make_subscript(_, _state)
>
, plus< distribute_subscript, distribute_subscript >
, minus< distribute_subscript, distribute_subscript >
, multiplies< distribute_subscript, distribute_subscript >
, divides< distribute_subscript, distribute_subscript >
, assign< distribute_subscript, distribute_subscript >
>
{};
template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c;
template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c
: transform< unroll_vector_expr_c< I, N > >
{
template< typename Expr, typename State, typename Data >
struct impl
: transform_impl< Expr, State, Data >
{
typedef
typename result_of::make_expr<
tag::comma
, typename boost::result_of<
distribute_subscript(
Expr
, typename result_of::make_expr<
tag::terminal
, boost::mpl::size_t< I - 1 >
>::type
)
>::type
, typename boost::result_of<
unroll_vector_expr_c< I + 1, N >(
Expr
)
>::type
>::type
result_type;
result_type operator()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return
make_expr<tag::comma>(
distribute_subscript()(
expr
, make_expr<tag::terminal>(
boost::mpl::size_t< I - 1 >()
)
)
, unroll_vector_expr_c< I + 1, N >() (
expr
)
);
}
};
};
template< std::size_t N >
struct unroll_vector_expr_c< N, N >
: transform< unroll_vector_expr_c< N, N > >
{
template< typename Expr, typename State, typename Data >
struct impl
: transform_impl< Expr, State, Data >
{
typedef
typename boost::result_of<
distribute_subscript(
Expr
, typename result_of::make_expr<
tag::terminal
, boost::mpl::size_t< N - 1 >
>::type
)
>::type
result_type;
result_type operator()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return
distribute_subscript()(
expr
, make_expr<tag::terminal>(
boost::mpl::size_t< N - 1 >()
)
);
}
};
};
struct unroll_vector_expr
: transform<unroll_vector_expr>
{
template< typename Expr, typename State, typename Data >
struct impl
: transform_impl< Expr, State, Data >
{
typedef
typename dimension<
typename boost::remove_reference<
typename boost::result_of<
_value(State)
>::type
>::type
>::type
dimension;
typedef
typename result_of::make_expr<
tag::comma
, typename boost::result_of<
unroll_vector_expr_c< 1, dimension::value >(
Expr
)
>::type
, State
>::type
result_type;
result_type operator()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return
make_expr<tag::comma>(
unroll_vector_expr_c< 1, dimension::value >()(
expr
)
, boost::ref(state)
);
}
};
};
我應該怎麼寫我的轉變,使得result_type
結果從operator()
匹配,並且適用於terminal
小號都是由價值和參考不放?
更新:代碼更新後埃裏克的答案。 result_type
和make_expr
之間僅存的失配是用於unroll_vector_expr_c
的第一實例化,其中terminal< mpl::size_t<0> >::type
由const引用而不是由值保持。奇怪的是,後續的具有較高索引的相同模板的實例化不會導致這個問題。
更新:我設法得到的代碼工作充分,修改distribue_subscript
轉化爲武力值取標索引後:
struct distribute_subscript
: or_<
scalar_grammar
, when<
vector_literal
, _make_subscript(_, _byval(_state)) // <-- HERE
>
, plus< distribute_subscript, distribute_subscript >
, minus< distribute_subscript, distribute_subscript >
, multiplies< distribute_subscript, distribute_subscript >
, divides< distribute_subscript, distribute_subscript >
, assign< distribute_subscript, distribute_subscript >
>
{};
我提到'deep_copy',因爲使用它會導致我的'result_type'和'make_expr'的實際結果不同。關於使用'boost :: ref'的觀點正是我對'make_expr'所缺少的東西,我只希望原始終端通過引用保存(一個保存在'state'中)。 –
謝謝埃裏克,我終於能夠完成這項工作!您是否願意評論我爲什麼需要上次修復?無論何時你有時間,當然。 –
'_make_subscript'是'proto :: functional :: make_expr'的一個typedef。像'proto :: result_of :: make_expr'一樣,它對它的參數是否是引用也很敏感。所以如果你想用'_make_subscript'來存儲一個孩子的價值,你必須確保它不是一個參考。你可能會想,「但是我將一個右值傳遞給'distribute_subscript'變換。爲什麼Proto認爲它是一個左值?」在C++ 03中,無法在其參數的右值上重載函數。所以'distribute_subscript :: operator()'推導出它的「狀態」參數是一個'const&'。 HTH –