
Joel Falcou wrote:
Eric Niebler a écrit :
This question has come up a couple of times. The solution isn't very pretty ... write a grammar that allows expressions with incompatible terminals, and then write a separate transform that checks the terminals for compatibility. This issue came up during Proto's review and I posted some example code here (see the SameTerminals transform): Well I thought to have template grammar ;) aka :
template<class T> struct simd_grammar : terminal< simd<T> > .... {};
Then vec<T> extends a domain which is based on simd_grammar<T>. Not sure it's more elegant though. I'll dig this during the week.
Ah, well that's a clever thought. Here's some code to get you started ... #include <boost/proto/proto.hpp> namespace mpl = boost::mpl; namespace proto = boost::proto; using proto::_; template<typename T> struct simd {}; template<typename T> struct simd_grammar : proto::or_< proto::terminal<simd<T> > , proto::nary_expr<_, proto::vararg<simd_grammar<T> > > > {}; template<typename Expr, typename T> struct simd_expr; template<typename T> struct simd_generator { template<typename Sig> struct result; template<typename This, typename Expr> struct result<This(Expr)> { typedef simd_expr<Expr, T> type; }; template<typename Expr> simd_expr<Expr, T> const operator()(Expr const &expr) const { simd_expr<Expr, T> that = {expr}; return that; } }; template<typename T> struct simd_domain : proto::domain<simd_generator<T>, simd_grammar<T> > {}; template<typename Expr, typename T> struct simd_expr { BOOST_PROTO_EXTENDS(Expr, simd_expr, simd_domain<T>) }; simd_expr<proto::terminal<simd<char> >::type, char> const simd_char = {{{}}}; simd_expr<proto::terminal<simd<int> >::type, int> const simd_int = {{{}}}; int main() { (simd_char + simd_char) * simd_char; (simd_int + simd_int) * simd_int; // ERROR, these are in different domains // (simd_char + simd_char) * simd_int; } -- Eric Niebler BoostPro Computing http://www.boostpro.com