Hi! I'm looking for some "lazy" version of boost::mpl::if_. I'm not very much into MPL, so I don't really know either if such a function exists in boost or whether it can be easily constructed. Platform: VC++7.1 Thx in advance, Agoston This example shows you how it may cause problems that both "branches" of if_ get evaluated: //------------------------------------------------------------ #include <iostream> #include <vector> #include <boost/mpl/if.hpp> #include <boost/type_traits.hpp> using namespace std; using namespace boost; using namespace mpl; template<typename T> struct t_type { typedef typename if_< is_arithmetic<T>, T, typename T::value_type>::type // ERROR! type; }; int _tmain(int argc, _TCHAR* argv[]) { cout << typeid(t_type<int>::type).name() << endl; // 'int' cout << typeid(t_type<vector<double> >::type).name() << endl; // 'double' return 0; } //------------------------------------------------------------ Error message: error C2825: 'T::value_type': cannot form a qualified name see reference to class template instantiation 't_type<T>' being compiled with [ T=int ]
Look in the mpl documentation under eval_if Robert Ramey Agoston Bejo wrote:
Hi! I'm looking for some "lazy" version of boost::mpl::if_. I'm not very much into MPL, so I
don't really know either if such a function exists in boost or whether it can be easily
constructed. Platform: VC++7.1
Thx in advance, Agoston
This example shows you how it may cause problems that both "branches" of if_ get evaluated:
//------------------------------------------------------------ #include <iostream> #include <vector> #include <boost/mpl/if.hpp> #include <boost/type_traits.hpp>
using namespace std; using namespace boost; using namespace mpl;
template<typename T> struct t_type { typedef typename if_< is_arithmetic<T>, T, typename T::value_type>::type // ERROR! type; };
int _tmain(int argc, _TCHAR* argv[]) { cout << typeid(t_type<int>::type).name() << endl; // 'int' cout << typeid(t_type<vector<double> >::type).name() << endl; // 'double' return 0; }
//------------------------------------------------------------ Error message:
error C2825: 'T::value_type': cannot form a qualified name see reference to class template instantiation 't_type<T>' being compiled with [ T=int ]
It seems to me that eval_if doesn't use lazy evaluation either. The error message quite obviously refers to an attempt of the compiler to evaluate the expression on the 'false' branch, whereas the condition (is_arithmetic<int>) is true to my best knowledge. Thx, Agoston --------------------------------------------------------------------- #include <iostream> #include <boost/mpl/eval_if.hpp> #include <boost/type_traits.hpp> #include <boost/mpl/identity.hpp> #include <vector> using namespace std; using namespace boost; using namespace mpl; template<typename T> struct value_type { typedef typename eval_if< is_arithmetic<T>, identity<T>, identity<typename T::value_type> >::type // ERROR type; }; int _tmain(int argc, _TCHAR* argv[]) { cout << typeid(value_type<int>::type).name() << endl; // ERROR cout << typeid(value_type<double>::type).name() << endl; cout << typeid(value_type< vector<int> >::type).name() << endl; cout << typeid(value_type< vector<double> >::type).name() << endl; return 0; } --------------------------------------------------------------------- Error: error C2825: 'T::value_type': cannot form a qualified name c:\guszti\prog\vcpp\Boost\xEvalIf\xEvalIf.cpp(27) : see reference to class template instantiation 'value_type<T>' being compiled with [ T=int ] error C2143: syntax error : missing ',' before 'value_type' error C2275: 'value_type' : illegal use of this type as an expression "Robert Ramey" <ramey@rrsd.com> az alábbiakat írta a következõ hírüzenetben: cqaid5$sp1$1@sea.gmane.org...
Look in the mpl documentation under eval_if
Robert Ramey
Agoston Bejo wrote:
Hi! I'm looking for some "lazy" version of boost::mpl::if_. I'm not very much into MPL, so I
don't really know either if such a function exists in boost or whether it can be easily
constructed. Platform: VC++7.1
Thx in advance, Agoston
This example shows you how it may cause problems that both "branches" of if_ get evaluated:
//------------------------------------------------------------ #include <iostream> #include <vector> #include <boost/mpl/if.hpp> #include <boost/type_traits.hpp>
using namespace std; using namespace boost; using namespace mpl;
template<typename T> struct t_type { typedef typename if_< is_arithmetic<T>, T, typename T::value_type>::type // ERROR! type; };
int _tmain(int argc, _TCHAR* argv[]) { cout << typeid(t_type<int>::type).name() << endl; // 'int' cout << typeid(t_type<vector<double> >::type).name() << endl; // 'double' return 0; }
//------------------------------------------------------------ Error message:
error C2825: 'T::value_type': cannot form a qualified name see reference to class template instantiation 't_type<T>' being compiled with [ T=int ]
Agoston Bejo wrote:
It seems to me that eval_if doesn't use lazy evaluation either. The error message quite obviously refers to an attempt of the compiler to evaluate the expression on the 'false' branch, whereas the condition (is_arithmetic<int>) is true to my best knowledge.
eval_if uses lazy evaluation to the extent possible: it accepts two nullary metafunctions and invokes one of them depending on how the condition evaluates. Your code computes T::value_type immediately, before either metafunction can be invoked. No library can change the properties of the C++ language. You only need to make a metafunction that gets the value_type and use that with eval_if: template <class T> struct get_value_type { typedef typename T::value_type type; }; template <class T> struct value_type : eval_if<is_arithmetic<T>, identity<T>, get_value_type<T> > {}; HTH, -- Dave Abrahams Boost Consulting http://www.boost-consulting.com
"Agoston Bejo" <gusz1@freemail.hu> wrote
template<typename T> struct value_type { typedef typename eval_if< is_arithmetic<T>, identity<T>, identity<typename T::value_type> >::type
// ERROR
type; };
In your example T::value_type is unconditionally evaluated, and eval_if will not help you in this particular case. You have to ensure that T::value_type is never mentioned in a template that can be possibly instantiated with a type that doesn't have this typedef (eval_if does this for ::type). You can either switch to using ::type instead of ::value_type, and then eval_if will probably help you, or just try something more basic, for example: template<typename T, typename IsAr> struct value_type_impl; template<typename T> struct value_type_impl<T, mpl::true_> : identity<T> {}; template<typename T> struct value_type_impl<T, mpl::false_> : identity<typename T::value_type> {}; template<typename T> struct value_type : value_type_impl<T, is_arithmetic<T>::type> {}; HTH, Arkadiy
participants (4)
-
Agoston Bejo
-
Arkadiy Vertleyb
-
David Abrahams
-
Robert Ramey