MciprianM
MciprianM

Reputation: 513

[C++ compile time assertions]: Can we throw a compilation error if some condition is not met?

I wrote a function:

template<int N> void tryHarder() {
    for(int i = 0; i < N; i++) {
        tryOnce();
    }
}

but I only want it to compile if N is in between 0 and 10. Can I do it? How?

Upvotes: 10

Views: 4830

Answers (4)

Aconcagua
Aconcagua

Reputation: 25536

Combined with the answers given so far already, the lower bound can be covered, too, by using unsigned int as template type. Negative values, if applied, will be converted to unsigned values high enough that they will be covered with the static_assert or the pre-C++11 solution anyway.

unsigned int additionally gives already semantically a hint that negative values shall not be applied to this template, which is why it (possibly) should be preferred in the specific case...

Upvotes: 1

pratikpc
pratikpc

Reputation: 690

#if !defined(__cplusplus)
#error C++ compiler required.
#endif

This is just an example.

Here is the source link: http://msdn.microsoft.com/en-us/library/c8tk0xsk(v=vs.71).aspx

All i am saying is that you can use #error also

It is a directive

Edit @Pratik Chowdhruy: I agree with Paul R. This does not answer the question directly. Sorry to the community

Upvotes: -2

rohitsan
rohitsan

Reputation: 1041

For pre C++11 compilers, you could implement a template parameter constraint on the non-type parameter N.

For a description of how to do this, please see http://stroustrup.com/bs_faq2.html#constraints

Upvotes: 2

jrok
jrok

Reputation: 55425

You can do it with static_assert declaration:

template<int N> void tryHarder() {

    static_assert(N >= 0 && N <= 10, "N out of bounds!");

    for(int i = 0; i < N; i++) {
        tryOnce();
    }
}

This feature is only avaliable since C++11. If you're stuck with C++03, take a look at Boost's static assert macro.

The whole idea of this are nice error messages. If you don't care for those, or can't even affor boost, you could do something as follows:

template<bool B>
struct assert_impl {
    static const int value = 1;
};

template<>
struct assert_impl<false> {
    static const int value = -1;
};

template<bool B>
struct assert {
    // this will attempt to declare an array of negative
    // size if template parameter evaluates to false
    static char arr[assert_impl<B>::value]; 
};

template<int N>
void tryHarder()
{
    assert< N <= 10 >();
}

int main()
{
    tryHarder<5>();  // fine
    tryHarder<15>();  // error, size of array is negative
}

Upvotes: 16

Related Questions