I'm trying to learn C++ by doing everything "the C++ way". I'm writing a program where I have all of these known values (at compile time). Here is my problem:
In my constructor I want to check to see if a passed value(an int) is one of 2,4,8,16 or 32 and throw an error elsewise. I've though about:
- making a C style array or ints
- creating a vector before by hand and interating through it to check
- making a list? I've never used lis开发者_C百科ts before though.
What I really want to do is make a const vector in a separate header file, this doesn't seem possible though.
What is the most elegant way to do this check?
Also, similarly is there any way to make a vector with a set number of known values (at compile time) in a header? If I can do const std::string a_str("a string");
I don't see why I can't use a similar technique for vectors.
What's wrong with:
if (!(n == 2 || n == 4 || n == 8 || n == 16 || n == 32))
{
// no!
}
If you want the "C++ way", a static array should do, with 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!
}
Modifying this list is simple, and I'm guessing the compiler may optimize this to my previous answer.
It's a bit of a trick, but I believe this works:
if (n & (n-1) != 0)
{
// not a power of two
}
If we're talking about bit twiddling sillyness, here's my try:
if ((n & 0x3E) != n || (n & n - 1) != 0)
throw std::runtime_error("not a power of two less than or equal to 32");
Bit twiddling sillyness is VERY C/C++, but only "elegant" if by elegant you mean "as few processor cycles as absolutely possible and in as terse a syntax as possible". Use a dictionary lookup or explicit check (such as std::find in GMan's answer), otherwise.
Readability is almost always preferrable to this kind of wackyness.
If you are really looking for doing it with a vector and want nice assignment operations have a look at boost::assign.
But you just really don't want to do it with a vector ;)
Edit: I just saw your "at compile time". Consider why this can't be done: std::vector
isn't a built in type. To have a mechanism to use somekind of smart assignment like that would require to built in support for it for the whole language and every user-defined type. Even if you don't need core language support and can do it with Templates this wouldn't be consistent with the overall style of the STL.
Use a normal C array, my C is rusty but here goes
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 ..... */
This might not fit the context of what you're trying to do, but you can use an enum.
Since this is compile time knowledge, I'll assume that these passed values are important at compile time. Using an enum, callers aren't trying to figure out what magic number to pass into your function.
typedef enum
{
Value1 = 2,
Value2 = 4,
Value4 = 8,
Value5 = 16,
Value6 = 32
} MyMagicType;
void MyFunction(MyMagicType theType)
{
...
}
The compiler will then enforce the value to be one of the above (well, unless you cast it, but that is a different matter) and throw an error should it not be one of the defined values.
精彩评论