GCC下,boost::mpl好象不能提供lazy evaluation
《C++ TMP》第四章提到boost::mpl::if_等元函数可以实现缓式评估(lazy evaluation),boost::mpl::or_等则具有短路行为(short-circuit behavior),但是我在g++编译器下试了一下,好象都不行。测试lazy evaluation的代码如下:
#include <iostream>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/identity.hpp>
namespace mpl = boost::mpl;
template <typename T>
struct test_lazy_evaluation
: mpl::if_< typename boost::is_scalar<T>::type
, mpl::identity<T&>, typename boost::add_reference<T const> >::type
{
};
int main()
{
typedef test_lazy_evaluation<int&>::type t1;
std::cout << boost::is_same<t1, int&>::value << std::endl;
return 0;
}
测试short-circuit behavior的代码如下:
#include <iostream>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_reference.hpp>
namespace mpl = boost::mpl;
template <typename T>
struct ShortCircuitTest
: mpl::or_<boost::is_reference<T>, boost::is_reference<T&> >
{
};
int main()
{
std::cout << ShortCircuitTest<int&>::type::value << std::endl;
return 0;
}
这两段代码都无法通过g++的编译,所报错误是一样的,mpl::if_<>和mpl::or_<>中本无需实例化的那部分也被实例化了,而该实例化会导致reference to reference的错误。 是我搞错了lazy evaluation和short-circuit behavior的真正意义。在前面两个测试用的元函数中,我将if_<>的第三个参数和or_<>的第二个参数都使用了T&来实例化,然后试图在main()的测试时用int&来实例化测试用元函数,从而导致了reference to reference的错误。我最初的理解是,if_<>在看到第一个参数为true时,就不会去碰第三个参数,同样or_<>在看到第一个参数为true时,也不会去碰第二个参数,结果不是这样的。
其实是我对lazy evaluation和short-circuit behavior的真正意义理解错了。正确的是:if_<>在看到第一个参数为true时,也要去检查第三个参数的声明是否有效,但不会去触碰它里面的东西(如::type或::value),同样or_<>在看到第一个参数为true时,也要检查第二个参数的声明,但也不会去触碰嵌套在里面的东西,除非嵌套的东西被显式调用。
还是以书中的例子为例,如果你这样写:
template <class T>
struct param_type
: mpl::if_<
typename boost::is_scalar<T>::type
, T
, typename boost::add_reference<T const>::type
>
{};
那么不管boost::is_scalar<T>::type是true还是false,编译器都要实例化boost::add_reference<T const>以获得嵌套在其内部的::type。而如果你这样写:
template <class T>
struct param_type
: mpl::if_< // forwarding to selected transformation
typename boost::is_scalar<T>::type
, mpl::identity<T>
, boost::add_reference<T const>
>::type
{};
则无论boost::is_scalar<T>::type是true还是false,编译器都会检查boost::add_reference<T const>的声明是否合法,但不会实例化它,直至你需要嵌套在其内部的::type。 所以说,1楼帖子中的代码不是检测lazy evaluation和short-circuit behavior的正确代码。理解了这些以后,我修改了代码,如下:
#include <iostream>
#include <boost/mpl/or.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_reference.hpp>
namespace mpl = boost::mpl;
template <typename T>
struct ErrorTest
{
typedef typename boost::is_reference<T&>::type type;
};
template <typename T>
struct LazyEvaluationTest
: mpl::if_< typename boost::is_reference<T>::type
, mpl::identity<T>, ErrorTest<T> >::type
{
};
template <typename T>
struct ShortCircuitTest
: mpl::or_<boost::is_reference<T>, ErrorTest<T> >
{
};
int main()
{
typedef LazyEvaluationTest<int&>::type t1;
std::cout << ShortCircuitTest<int&>::value << std::endl;
return 0;
}
这一次,程序可以正常通过编译了。
页:
[1]