繁体   English   中英

c ++:是否有类似“boost / std typetraits conditional”的东西在编译时生成一个值(不是一个类型)?

[英]c++: Is there something like “boost/std typetraits conditional” that generates a value (not a type) at compile time?

我目前正在执行以下操作以在编译时生成一个值,该函数有效:

        //if B is true, m_value = TRUEVAL, else FALSEVAL, T is the value type
        template<bool B, class T, T TRUEVAL, T FALSEVAL>
        struct ConditionalValue
        {
            typedef T Type;

            Type m_value;

            ConditionalValue():
            m_value(TRUEVAL)
            {}
        };

        template<class T, T TRUEVAL, T FALSEVAL>
        struct ConditionalValue<false, T, TRUEVAL, FALSEVAL>
        {
            typedef T Type;

            Type m_value;

            ConditionalValue():
            m_value(FALSEVAL)
            {}
        };

然后你可以简单地做这样的事情:

template<class T>
void loadPixels(uint32 _w, uint32 _h, T * _pixels)
{
    PixelDataType::Type pixelType = PixelDataType::Auto; //enum I want to set

    ConditionalValue<boost::is_same<T, uint8>::value, PixelDataType::Type, PixelDataType::UInt8, PixelDataType::Auto> checker;
    pixelType = checker.m_value;

   ConditionalValue<boost::is_same<T, uint16>::value, PixelDataType::Type, PixelDataType::UInt16, PixelDataType::Auto> checker2;
   pixelType = checker2.m_value;

   ...

}

我知道这个例子没有多大意义,但我使用该代码在编译时设置枚举的值。所以这是我的问题: 在std / boost类型特征中是否有类似的东西? 浏览引用时,我发现条件几乎完全符合我的要求,但只生成一个类型,而不是一个值。

编辑:

更新的例子。

EDIT2:

我刚刚意识到boost :: is_same :: value是解决我问题所需要的全部内容。至于问题的答案:std / boost中似乎没有任何东西包含在thiton中有充分理由

编辑3:如果您仍在寻找在编译时创建值的解决方案,您可以使用我的代码。 如果你正在寻找非常接近boost / stl的东西KerrekNawaz似乎也是有效的解决方案。 如果你正在寻找一个在编译时分配正确枚举的解决方案, Luc Touraille的方法似乎很有意思,即使我认为这对我的情况来说太过分了!

std::conditionalstd::integral_constant可能在某些情况下有效:

template <bool B, typename T, T trueval, T falseval>
struct conditional_val : std::conditional<B,
       std::integral_constant<T, trueval>,
       std::integral_constant<T, falseval>>::type
{ };

现在使用:

const int q = conditional_val<B, int, 12, -8>::value;

等价的:

const int q = B ? 12 : -8;

Boost.MPL有一组用于在编译时操作数据类型的类,以及一些算术运算。 这些类将值包装到一个类型中,例如,整数4可以由类型mpl::int_<4>

您可以在编译时使用这些条件:

typedef typename 
    mpl::if_< 
        boost::is_same< T, uint8 >, 
        mpl::int_< 42 >, 
        mpl::int_< 187 >
    >::type result;

int i = result::value;

MPL还提供了一个通用的积分包装器 ,可以与枚举一起使用:

template<class T>
void loadPixels(uint32 _w, uint32 _h, T * _pixels)
{
    PixelDataType::Type pixelType = PixelDataType::Auto; //enum I want to set

    typedef typename mpl::if_<
        boost::is_same<T, uint8>, 
        mpl::integral_c<PixelDataType::Type, PixelDataType::UInt8>,
        mpl::integral_c<PixelDataType::Type, PixelDataType::Auto>
    >::type checker;

    pixelType = checker::value;

    typedef typename mpl::if_<
        boost::is_same<T, uint16>, 
        mpl::integral_c<PixelDataType::Type, PixelDataType::UInt16>,
        mpl::integral_c<PixelDataType::Type, PixelDataType::Auto>
    >::type checker2;

    pixelType = checker2::value;

    ...
}

如果您有很多这样的映射要做,您可以考虑使用混合编译时/运行时数据结构,例如fusion :: map ,但这可能有点矫枉过正:):

typedef fusion::map<
    fusion::pair<uint8, PixelDataType::Type>,
    fusion::pair<uint16, PixelDataType::Type> >
map_type;

map_type pixelTypesMap(
    make_pair<uint8>(PixelDataType::UInt8),
    make_pair<uint16>(PixelDataType::UInt16));

...

template<class T>
void loadPixels(uint32 _w, uint32 _h, T * _pixels)
{
    // need special handling if T is not in the map
    PixelDataType::Type pixelType = fusion::at_key<T>(pixelTypesMap);

    ...
}

我认为这是一个简单的答案:因为运算符?:可以很好地选择值。 类型更难选择,这就是为什么存在boost构造的原因。 对于病理情况,boost :: mpl magic Luc建议很好,但它应该是非常罕见的。

我遇到了一个我需要做的事情? (比较值,返回值),但使用模板专门化(为什么你需要它?简单:编译时间评估?可能导致“无法访问的代码”警告)

因此,适用于您的原始问题以及我的imho的最标准解决方案是:

std::conditional<myval, 
                 std::integral_constant<T, val>, 
                 std::integral_constant<T, val>
                >::type::value;

现在简单地用std::is_same替换“myval”并且你有一个解决方案(比较类型,返回值),而上面是我的情况的解决方案(比较值,返回值<=> ?

你可以写自己:

namespace extend 
{
  template<bool B, class T, T X, T Y>  
  struct conditional
  {
       static const T value = X;
  };
  template<class T, T X, T Y>  
  struct conditional<false,T,X,Y>
  {
       static const T value = Y;
  };
}

//test
assert(conditional<std::is_same<int,int>::value, int, 10, 20>::value == 10);
assert(conditional<std::is_same<int,char>::value, int, 10, 20>::value == 20);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM