How can I force a c++ class method to accept only a handful of integer literals?
There is a class I'm refactoring which currently has a method:
void resize(size_t sz)
In the current codebase, sz is always 0,1,2,or 3. The underlying class is changing from dynamic allocation to a preallocated array of maxsize==3.
How can I get a build time error if someone tries to resize to sz>3 ? It is easy enough to add a runtime check. But I'd rather get a compile-time check that fails sooner.
I don't want to change any existing code that makes calls with an integer literal that is in-bounds ,e.g.:
x.resize(2)
should still compile as is.
But if someone comes along and tries to
x.resize(4)
or
x.resize(n)
it should fail to compile or link.
I was thinking about a template specialized on int that is undefined for anything other than {0,1,2,3}. But I'm not sure quite how to make it do what I want within the confines of standard c++.
edit:
I should elaborate on my thoughts of using the template. I am quite willing to change the declaration of the resize function. I am not willing to change the calling code.
e.g. I was thinking something like
void resize( ConstructedFromLiteral<0,3> sz)
or
void resize( ConstructedFromLiteral<0> sz)
void resize( ConstructedFromLiteral<1> sz)
void resize( ConstructedFromLiteral<2> sz)
void resize( ConstructedFromLiteral&l开发者_如何学Ct;3> sz)
There's no way you can get a compile-time check for a run-time value. Imagine if you said,
resize(read_some_number_from_disk());
How is the compiler supposed to check that?
However, you can make the function a template, since template parameters are known at compile time:
class Foo
{
template <unsigned int N> void resize()
{
static_assert(N < 4, "Error!");
//...
}
//...
};
If you don't have static asserts, you can rig up your own static-assert class that'll fail to compile:
template <bool> struct ecstatic_assert; // no definition!
template <> struct ecstatic_assert<true> { } ;
Usage:
... resize ... { ecstatic_assert<N < 4> ignore_me; /* ... */ }
I'd use static_assert
to check this at compile time:
struct foo {
template <int N>
void resize() {
static_assert(N >= 0 && N < 4);
}
};
You get static_assert
builtin in C++11, but it's easy enough to implement in C++03 too. Compared to specialisations it saves you from some quite tedious code duplication.
You can't do it. You can't keep function calls to resize as is, and check n
at compile time since its a runtime value. You will need to refactor your code in order to get a compile time error (for instance std/boost static_assert).
You could make four public inlined specialized templates for ints {0, 1, 2, 3}. These would be simple one-line functions that call a private normal, generic function for any int.
EDIT: For the naysayers who say it can't be done using specialized templates (why the downvotes?):
class Demo {
private:
template<int MyInt>
void PrivateFunction() {
cout << MyInt << endl;
}
public:
template<int MyInt> void PublicFunction();
template<> void PublicFunction<0>() { PrivateFunction<0>(); }
template<> void PublicFunction<1>() { PrivateFunction<1>(); }
template<> void PublicFunction<2>() { PrivateFunction<2>(); }
template<> void PublicFunction<3>() { PrivateFunction<3>(); }
};
Try calling Demo::PublicFunction<4>() and you'll get a linker error. Accomplishes the same thing and useful if you don't have / don't want to make a static_assert.
As others mentioned, not so easy to check the value of a parameter...
I don't like this answer for hopefully obvious reasons, but it does satisfy your stated requirements:
struct x {
void true_resize(int n) { }
template <int N> void template_resize();
};
template<> void x::template_resize<0>() { true_resize(0); }
template<> void x::template_resize<1>() { true_resize(1); }
template<> void x::template_resize<2>() { true_resize(2); }
template<> void x::template_resize<3>() { true_resize(3); }
#define resize(x) template_resize<x>();
int main () {
x x;
x.resize(2);
x.resize(4);
}
In case it isn't obvious, the #define
doesn't obey C++ scope rules, and so ruins the name resize
for all other uses.
精彩评论