[英]C++ Template MetaProgramming: Compile Time Conditional Operator on Template Type
[英]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的東西Kerrek或Nawaz似乎也是有效的解決方案。 如果你正在尋找一個在編譯時分配正確枚舉的解決方案, Luc Touraille的方法似乎很有意思,即使我認為這對我的情況來說太過分了!
std::conditional
和std::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.