C++11 C++;类型选择中的模板元编程问题

C++11 C++;类型选择中的模板元编程问题,c++11,boost,C++11,Boost,下面的代码说明了我的问题 #include <type_traits> #include <limits> #include <cstdint> #include <boost/mpl/if.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> /////////////////////////////////////////////

下面的代码说明了我的问题

#include <type_traits>
#include <limits>
#include <cstdint>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>

/////////////////////////////////////////////////////////////////
// safe_signed_range

template <
    std::intmax_t MIN,
    std::intmax_t MAX
>
struct safe_signed_range {
};

/////////////////////////////////////////////////////////////////
// safe_unsigned_range

template <
    std::uintmax_t MIN,
    std::uintmax_t MAX
>
struct safe_unsigned_range {
};

template<class T, class U>
using calculate_max_t = typename boost::mpl::if_c<
    std::numeric_limits<T>::is_signed
    || std::numeric_limits<U>::is_signed,
    std::intmax_t,
    std::uintmax_t
>::type;

template<typename T, typename U>
struct test {

    typedef calculate_max_t<T, U> max_t;
    static_assert(std::is_same<max_t, std::intmax_t>::value, "unexpected value for max_t");
    static_assert(std::is_signed<max_t>::value, "check parameter");

/*
    typedef typename boost::mpl::if_c<
        std::is_signed<max_t>::value,
        safe_signed_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()>,
        safe_unsigned_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()>
    >::type type;
*/

    typedef typename boost::mpl::eval_if_c<
        std::is_signed<max_t>::value,
        boost::mpl::identity<safe_signed_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()> >,
        // error shows up here
boost::mpl::identity<safe_unsigned_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()> >
    >::type type;
};

test<int, int> t1;
//test<int, unsigned> t2;
//test<unsigned, int> t3;
//test<unsigned, unsigned> t4;

int main(){
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
/////////////////////////////////////////////////////////////////
//安全签名范围
模板<
标准::intmax\u t MIN,
标准::intmax\u t MAX
>
结构安全签名范围{
};
/////////////////////////////////////////////////////////////////
//安全\u无符号\u范围
模板<
标准::uintmax\u t MIN,
标准::uintmax\u t MAX
>
结构安全\u无符号\u范围{
};
模板
使用calculate\u max\u t=typename boost::mpl::if\u c<
标准::数值限制::是否签名
||标准::数值限制::已签名,
标准::intmax\U t,
标准:uintmax\u t
>::类型;
模板
结构测试{
类型定义计算最大值最大值;
静态断言(std::is_same::value,“max_t的意外值”);
静态断言(std::is_signed::value,“检查参数”);
/*
typedef typename boost::mpl::if_c<
std::is_signed::value,
安全标志范围,
安全\u无符号\u范围
>::类型类型;
*/
typedef typename boost::mpl::eval_if_c<
std::is_signed::value,
boost::mpl::identity,
//错误显示在这里
boost::mpl::identity
>::类型类型;
};
测试t1;
//测试t2;
//试验t3;
//测试t4;
int main(){
返回0;
}
错误显示为“铿锵编译器”

/Users/robertramey/WorkingProjects/safe_numerics/test/test_z.cpp:116:50:Non-type模板参数的计算结果为-9223372036854775808,不能缩小为类型“std::uintmax_t”(也称为“unsigned long”)


看起来Boost Mpl没有选择正确的类型。首先,我怀疑(实际上仍然怀疑)if的所有参数都在扩展,所以我改为使用eval_if,但我还是遇到了问题。我加入了static_assert来检查参数,可以通过最简单的测试使其失败——尽管它在所有组合中都失败了。如果有人能向我解释我的错误,我将不胜感激

问题在于,您正在实例化一个模板(不管它是否为
boost::mpl::identity
),该模板对于当前类型的
safe\u unsigned\u range
无效。解决方案是基于传递给
boost::mpl::eval\u if\u c
的布尔谓词推迟模板实例化

为此,我们必须首先为两种范围类型编写自己的
identity

template<typename Integer, Integer Top, Integer Bottom>
struct defer_unsigned_lazily {
    using type = safe_unsigned_range<Top, Bottom>;
};

template<typename Integer, Integer Top, Integer Bottom>
struct defer_signed_lazily {
    using type = safe_signed_range<Top, Bottom>;
};
之后,它应该按照预期在Clang和GCC上编译


好的-这很有效-干得好,非常感谢。当然,这就是我使用mpl:identity的动机,我认为它应该做同样的事情。我会调查的。再次感谢。
using limits = std::numeric_limits<max_t>;
typedef typename boost::mpl::eval_if_c<
    std::is_signed<max_t>::value, 
    defer_signed_lazily<max_t, limits::min(), limits::max()>, 
    defer_unsigned_lazily<max_t, limits::min(), limits::max()>
>::type type;