簡體   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