Код ниже пытается проверить поведение короткого замыкания boost::mpl::or_
а также boost::mpl::and_
:
#include <vector>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_scalar.hpp>
// Dummy is forward declared and never defined
template <class T> class dummy;
// If T is a scalar evaluates to T without trying to compute the result of
// boost::mpl::is_scalar< dummy<T>, otherwise it fails at compile time.
template <class T>
class testOr
: public boost::mpl::eval_if<
boost::mpl::or_< boost::is_scalar<T>, boost::is_scalar< dummy<T> > >,
boost::mpl::identity<T>,
dummy<T>
>
{};
// If T is not a scalar evaluates to T without trying to compute the result of
// boost::mpl::is_scalar< dummy<T>, otherwise it should fail at compile time.
template <class T>
class testAnd
: public boost::mpl::eval_if<
// It appears that is_scalar< dummy<T> > is not instantiated and the operation
// evaluates to false
boost::mpl::and_< boost::is_scalar<T>, boost::is_scalar< dummy<T> > >,
dummy<T>,
boost::mpl::identity<T>
>
{};
int main() {
static_assert(boost::is_same< testOr< double >::type, double>::type::value,"Fails at compile time");
// The following line causes failures at compile time due to incomplete type definition
//static_assert(boost::is_same< testOr< std::vector<double> >::type, double>::type::value,"Fails at compile time");
static_assert(boost::is_same< testAnd< std::vector<double> >::type, std::vector<double> >::type::value,"Fails at compile time");
// The following should cause failure at compile time due to incomplete type definition, but works instead!
static_assert(boost::is_same< testAnd< double >::type , double >::type::value,"Fails at compile time");
return 0;
}
Хотя я ожидаю, что этот код потерпит неудачу во время компиляции из-за неполного определения типа, на самом деле он работает:
>icpc --version
icpc (ICC) 12.1.3 20120212
Copyright (C) 1985-2012 Intel Corporation. All rights reserved.
>icpc -gcc-name=gcc-4.5 -std=c++0x -o ex-4.0.x ex-4.0.cc
Итак, смысл, который я хотел бы понять:
Есть ли несоответствие в пути boost::mpl::or_
а также boost::mpl::and_
оцените их аргументы или, скорее всего, есть ошибка в коде, которую я не могу отловить?
Почему вы думаете, что второй аргумент or_
не будет оцениваться? is_scalar
может использоваться с неопределенными типами.
Например, в этом случае вы также получите ошибку.
// If T is not a scalar evaluates to T without trying to compute the result of
// boost::mpl::is_scalar< dummy<T>, otherwise it should fail at compile time.
template <class T>
class testAnd
: public boost::mpl::eval_if<
// It appears that is_scalar< dummy<T> > is not instantiated and the operation
// evaluates to false
boost::mpl::and_< boost::is_scalar<T>, boost::is_scalar< dummy<T> > >,
boost::mpl::identity<T>,
dummy<T>
>
{};
поскольку boost::is_scalar<T>
верно, но boost::is_scalar<dummy<T>>
ложно в вашем случае, так
Посмотрите. http://liveworkspace.org/code/a792e18ca16a0410a67a6eee8c550bd9
У вас логическая ошибка в ваших мыслях — ||
будет короткое замыкание IIF первый аргумент оценивается как true
. is_scalar<std::vector<double>>
является false
Это означает, что второй аргумент должен быть оценен. По сравнению, &&
будет короткое замыкание, если первый аргумент false
, который имеет место, как сказано выше.