我正在尝试通过“C ++方式”做所有事来学习C ++。我正在编写一个程序,其中包含所有这些已知值(在编译时)。这是我的问题:
在我的构造函数中,我想检查传递的值(一个int)是否是2,4,8,16或32中的一个,否则抛出一个错误。我想说的是:
我真正想做的是在单独的头文件中创建一个const向量,但这似乎不可能。
这种检查最优雅的方式是什么?
此外,类似地,是否有任何方法可以在标题中创建具有已知值(在编译时)的设定数量的向量?如果我可以做const std::string a_str("a string");
我不明白为什么我不能对矢量使用类似的技术。
答案 0 :(得分:8)
出了什么问题:
if (!(n == 2 || n == 4 || n == 8 || n == 16 || n == 32))
{
// no!
}
如果你想要“C ++方式”,静态数组应该用find
:
template <typename T, size_t N>
T* endof(T (&pArray)[N])
{
return &pArray[0] + N;
}
static const int OkNumbers[] = {2, 4, 8, 16, 32};
static const int* OkNumbersEnd = endof(OkNumbers);
if (std::find(OkNumbers, OkNumbersEnd, n) == OkNumbersEnd)
{
// no!
}
修改此列表很简单,我猜测编译器可以将其优化为我之前的答案。
答案 1 :(得分:6)
这有点戏法,但我相信这有效:
if (n & (n-1) != 0)
{
// not a power of two
}
答案 2 :(得分:2)
如果我们谈论的是愚蠢的话,这是我的尝试:
if ((n & 0x3E) != n || (n & n - 1) != 0)
throw std::runtime_error("not a power of two less than or equal to 32");
有点狡猾的愚蠢是非常C / C ++,但只有“优雅”,如果优雅,你的意思是“尽可能少的处理器周期,尽可能简洁的语法”。使用字典查找或显式检查(例如在GMan的答案中使用std :: find),否则。
可读性几乎总是偏向于这种古怪。
答案 3 :(得分:1)
如果你真的想用矢量做它并希望好的赋值操作看一下boost :: assign。
但你真的不想用矢量来做;)
编辑:我刚看到你的“编译时”。考虑为什么不能这样做:std::vector
不是内置类型。要有一种机制来使用某种智能分配,就需要为整个语言和每个用户定义的类型内置支持它。即使您不需要核心语言支持并且可以使用模板,这也不符合STL的整体风格。
答案 4 :(得分:0)
使用普通的C数组,我的C生锈但是这里
int array[] = {2,4,8,16,32};
/* now loop over the array and check */
for( i = 0; i< size_of_array ; i++) {
if (array[i] == input_int)
/* you get the idea ..... */
答案 5 :(得分:0)
这可能不符合您尝试执行的操作,但您可以使用枚举。
由于这是编译时知识,我将假设这些传递的值在编译时很重要。使用枚举,调用者不会试图找出传递给你的函数的幻数。
typedef enum
{
Value1 = 2,
Value2 = 4,
Value4 = 8,
Value5 = 16,
Value6 = 32
} MyMagicType;
void MyFunction(MyMagicType theType)
{
...
}
然后,编译器会强制该值成为上述之一(好吧,除非你强制转换它,但这是另一回事)并且如果它不是定义的值之一则抛出错误。