2015-02-06 71 views
1

我试图写一个函数,将采取任何形式的int或枚举。 我试过提供两个版本:编写一个函数,使用INT或枚举参数

template<typename E>int bit_num (const E bitPatA) 
template<typename E>int bit_num (enum bitPatA) 

枚举版本不编译。

我发现is_enum和enable_if但一直未能拿出一个咒语做到以下几点:

template <typename E>int bit_num <E bitPatA) 
{ 
if is_enum typedef typename std::underlying_type<E>::type int_T; 
if !is_enum typedef E int_T; 
... 
} 

所有is_enum的案例似乎刚刚打印出的文本,而不是像做有用控制模板的生成。

我发现,工会会做什么,我想要做的

<template E>int bit_num (E bitPatA) 
{ 
union {uintmax_t i; enum e;} bitpat; 

bitPat.i = 0;  // clear cruft 
bitPat.e = bitPatA; // load from enum 

        // use from int 
if ((bitPat.i == 0) || ((bitPat.i & ~(bitPat.i - 1)) != bitPat.i)) return -1; 
... 
} 

一部分,但是这并没有让我得到底层那种为int。

我想探索各种大小的编译器优化。


[代码和注释错误]

using namespace std; 

int bit_num (const enum bitPatA) 
{ 
    return -1; 
} 

template <typename T> 
struct identity 
{ 
    using type=T; 
}; 

template <typename E> 
typename enable_if< /* is_enum<E>{} ||*/ is_integral<E>{}, int>::type 
bit_num (const E bitPatA) 
{ 
    return -1; 
} 

误差

 
||=== Build: Debug in Bit_num (compiler: GNU GCC Compiler) ===| /home/jfw/Documents/Bit_num/BitTools.cpp|13|error: use of enum ‘bitPatA’ without previous declaration| 
+1

如果您告诉我们错误,并创建一个[最小,完整和可验证示例](http://stackoverflow.com/help/mcve)向我们展示如何使用这些函数,那么我们将会更好来帮你。 – 2015-02-06 19:40:28

+0

如果您使用的是C++ 11,那么您可以尝试查看['static_assert'](http://en.cppreference.com/w/cpp/language/static_assert)和[''](http:/ /en.cppreference.com/w/cpp/header/type_traits)限制生成 – Conduit 2015-02-06 19:43:48

+0

@Joachim using namespace std; int bit_num(const enum bitPatA){return -1; } template struct identity {using type = T;}; 模板 类型名称enable_if {} || */is_integral {},int>的::类型Bit_Num说(常量ËbitPatA) { 返回-1; }错误是|| ===构建:Bit_num中的调试(编译器:GNU GCC编译器)=== | /home/jfw/Documents/Bit_num/BitTools.cpp|13|error:使用没有预先声明的枚举'bitPatA'| – jfwfmt 2015-02-07 00:31:24

回答

1

你可能组合寻找enable_iftype traits

template <typename T> 
typename std::enable_if<std::is_enum<T>{} || std::is_integral<T>{}, int>::type 
bit_num (T t); 

钍如果参数是枚举类型或整数类型,函数将只是重载解析的候选对象。

你要建立在你的问题的类型定义可以使用辅助特征来实现:

template <typename T> struct identity {using type=T;}; 

用法是

using int_T = typename std::conditional<std::is_enum<T>{}, 
             std::underlying_type<E>, 
             identity<E>>::type::type; 
+0

Columbo谢谢,您使用enable_if的建议确实会阻止为非适当类型(例如:float)生成函数。 – jfwfmt 2015-02-07 00:21:38

+0

如果!is_enum和is_enum“typedef underlying_type int_T”,我仍然试图生成“typedef E int_T”。我尝试了使用两个“using”语句的建议,其中一个使用“is_enum”,另一个使用“!is_enum”,但我得到了“错误:使用int_T ='的冲突声明,并引用了每条using语句。 typdef for is_enum和另一个for!is_enum?谢谢 – jfwfmt 2015-02-07 00:42:09

+0

@jfwfmt这是正确的我的答案 – Columbo 2015-02-07 07:22:07

0

OK,感谢所有(@columbo, @joachim),这里是我的代码使用你的一些建议:

using namespace std; 
template <typename T> struct identity {using type=T;}; 

template <typename E> 
typename enable_if<is_integral<E>{}, int>::type bit_num (const E bitPatA) 
{ 
    using int_T = E; 
               // ignore truncation warnings for mask* 
    const int_T mask1 = 0xAAAAAAAAAAAAAAAALLU; // bits under mask position contains 1 
    const int_T mask2 = 0xCCCCCCCCCCCCCCCCLLU; // bits under mask position contains 2 
    const int_T mask3 = 0xF0F0F0F0F0F0F0F0LLU; 
    const int_T mask4 = 0xFF00FF00FF00FF00LLU; 
    const int_T mask5 = 0xFFFF0000FFFF0000LLU; 
    const int_T mask6 = 0xFFFFFFFF00000000LLU; // bits under mask position contains 32 
    size_t  sum = 0;      // accumulator and return value 
    int   bit = 1;      // sliding bit position value 

    // return error if no bits or more than one 
    if ((bitPatA == 0) || ((bitPatA & ~(bitPatA - 1)) != bitPatA)) return --sum; 

    sum += (mask1 & bitPatA) ? bit : 0;   // if non-zero under mask, add bit value 
    bit <<= 1;         // multiply bit by 2 
    sum += (mask2 & bitPatA) ? bit : 0; 
    bit <<= 1; 
    sum += (mask3 & bitPatA) ? bit : 0; 
    if (mask4 == 0) return sum;     // are the rest of the tests nugatory? 
    bit <<= 1; 
    sum += (mask4 & bitPatA) ? bit : 0; 
    if (mask5 == 0) return sum; 
    bit <<= 1; 
    sum += (mask5 & bitPatA) ? bit : 0; 
    if (mask6 == 0) return sum; 
    bit <<= 1; 
    sum += (mask6 & bitPatA) ? bit : 0; 
    return sum; 
} 

template <typename E> 
typename enable_if<is_enum<E>{}, int>::type bit_num (const E bitPatA) 
{ 
    using int_T = typename conditional<is_enum<E>{}, underlying_type<E>, identity<E> >::type::type; 
    return bit_num (static_cast<int_T>(bitPatA)); 
} 

第一个版本bit_num()适用于整数类型,第二类适用于枚举类型。第二个将参数转换为整数并调用第一个参数。

我现在明白int bit_num(const enum foo)被解析为常量“enum foo”,而不是名为“foo”的“const enum”参数。

我仍然不明白如何有条件地将int_T的一个定义放在bit_num()的单个版本中,但是使用仅为枚举参数生成的第二个bit_num(),并传递参数值和类型做我需要的。