找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 5837|回复: 2

GCC下,boost::mpl好象不能提供lazy evaluation

[复制链接]
发表于 2008-9-20 17:35:06 | 显示全部楼层 |阅读模式
《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的错误。
 楼主| 发表于 2008-9-20 17:35:14 | 显示全部楼层
是我搞错了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。
 楼主| 发表于 2008-9-20 17:35:22 | 显示全部楼层
所以说,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;
}

这一次,程序可以正常通过编译了。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-3 00:57 , Processed in 0.014523 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表