我尝试用新版本的 boost 1.86 来编译使用非常旧的 boost 版本(例如 1.30 之类)的旧代码(~15 年前 - luabind)。
我用
apply_if
替换了一些 eval_if
用法,就像 boost 1.32 发行说明中建议的那样。但是我遇到了一些编译错误。我尝试在下面准备一些有问题的代码的最小示例。
#include <boost/mpl/end.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/move/detail/meta_utils.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/list/list10.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
#include <iostream>
struct unspecified {
typedef unspecified type;
};
template<class T, class X1 = unspecified, class X2 = unspecified, class X3 = unspecified>
struct class_;
double is_not_unspecified_helper(const unspecified*);
char is_not_unspecified_helper(...);
template<class T>
struct is_not_unspecified
{
BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
typedef boost::mpl::bool_<value> type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_not_unspecified, (T))
};
template<class Predicate>
struct get_predicate
{
typedef typename boost::mpl::and_<
Predicate
, is_not_unspecified<boost::mpl::_1>
> type;
};
template<class Parameters, class Predicate, class DefaultValue>
struct extract_parameter
{
typedef typename get_predicate<Predicate>::type pred;
typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
typedef typename boost::mpl::eval_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
, boost::mpl::identity<DefaultValue>
, iterator
>::type type;
};
template<class T, class X1, class X2, class X3>
struct class_ {
class_(const char* name)
{
std::printf("class_(%s)\n", name);
}
typedef typename extract_parameter<
boost::mpl::list3<X1, X2, X3>
, boost::mpl::or_<
boost::is_base_and_derived<boost::mpl::_, T>
, boost::is_base_and_derived<boost::mpl::_, T>
>
, unspecified
>::type bases_t;
};
class A {
public:
typedef A type;
};
class B :
public A
{
public:
typedef B type;
void foo()
{
class_<B, A>("B");
}
};
int main()
{
}
编译错误:
1>main.cpp(50,5): error C2039: 'type': is not a member of 'boost::mpl::eval_if<boost::is_same<Iterator,LastIterator>,boost::mpl::identity<DefaultValue>,boost::mpl::l_iter<boost::mpl::list3<X1,X2,X3>>>'
1>main.cpp(50,5): error C2039: with
1>main.cpp(50,5): error C2039: [
1>main.cpp(50,5): error C2039: Iterator=boost::mpl::l_iter<boost::mpl::list3<A,unspecified,unspecified>>,
1>main.cpp(50,5): error C2039: LastIterator=boost::mpl::l_iter<boost::mpl::l_end>,
1>main.cpp(50,5): error C2039: DefaultValue=unspecified,
1>main.cpp(50,5): error C2039: X1=A,
1>main.cpp(50,5): error C2039: X2=unspecified,
1>main.cpp(50,5): error C2039: X3=unspecified
1>main.cpp(50,5): error C2039: ]
1>main.cpp(50,10): error C3646: 'type': unknown override specifier
1>main.cpp(50,5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>Done building project "eval_if_compilation.vcxproj" -- FAILED.
我很确定原因与
extract_parameter::iterator
类型定义有关。当我用简单的 unspecified
结构替换它时,它编译得很好。我相信原因是它找不到iterator::type
类型。然而它定义良好,我不明白为什么它会导致错误。
看起来
identity<>
周围的包裹 iterator
不见了。
using type = boost::mpl::eval_if< //
boost::is_same<iterator, typename boost::mpl::end<Parameters>>, //
boost::mpl::identity<DefaultValue>, //
boost::mpl::identity<iterator> //
>::type;
让它为我编译(修复包含)。
#include <boost/move/detail/meta_utils.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/list/list10.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/preprocessor/enum_params_with_a_default.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <cstdio>
struct unspecified {
typedef unspecified type;
};
template<class T, class X1 = unspecified, class X2 = unspecified, class X3 = unspecified>
struct class_;
double is_not_unspecified_helper(const unspecified*);
char is_not_unspecified_helper(...);
template<class T>
struct is_not_unspecified
{
BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
typedef boost::mpl::bool_<value> type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_not_unspecified, (T))
};
template<class Predicate>
struct get_predicate
{
typedef typename boost::mpl::and_<
Predicate
, is_not_unspecified<boost::mpl::_1>
> type;
};
template<class Parameters, class Predicate, class DefaultValue>
struct extract_parameter
{
using pred = typename get_predicate<Predicate>::type;
using iterator = typename boost::mpl::find_if<Parameters, pred>::type;
using type = boost::mpl::eval_if< //
boost::is_same<iterator, typename boost::mpl::end<Parameters>>, //
boost::mpl::identity<DefaultValue>, //
boost::mpl::identity<iterator> //
>::type;
};
template<class T, class X1, class X2, class X3>
struct class_ {
class_(char const* name) { std::printf("class_(%s)\n", name); }
typedef typename extract_parameter<
boost::mpl::list3<X1, X2, X3>
, boost::mpl::or_<
boost::is_base_and_derived<boost::mpl::_, T>
, boost::is_base_and_derived<boost::mpl::_, T>
>
, unspecified
>::type bases_t;
};
class A {
public:
typedef A type;
};
class B :
public A
{
public:
typedef B type;
void foo()
{
class_<B, A>("B");
}
};
int main()
{
}