Generating Custom Compile Time Errors

Started by
4 comments, last by Zakwayda 16 years, 3 months ago
I'm looking for a way to invoke a custom compile time error. I'm working with a lot of templates and would like to have the compiler emit a more meaningful message when particular errors occur. I'm working on a math package with highly flexible matrices, vectors, and other linear algebra constructs. Here's what a matrix declaration may look like.
math::matrix<float, math::dim_static2<4, 4>, math::row_major, math::column_major> mat;
This creates a (statically sized) 4 by 4 matrix of floats with a row major layout in memory using column major vector notation. (btw, I've been working on this due to some problems I had earlier with matricies which I received a lot of help with from this forum. :-) ) The templates I have are designed to work with the meta types above, such as math::row_major. If instead of specifying math::row_major above, a user specifies int, the compiler complains that mat is an instantiation of an abstract type because the at() member function is pure virtual. This is absolutely correct, but the error is confusing and misleading. I'm looking for a way to tell the compiler that if some code is reached, it should output a particular message. Something like this.
template<typename T>
void some_func(const T& arg)
{
    #compile_error("only float and double types allowed")
}
void some_func<float>(const float& arg)
{
    std::cout << arg;
}
void some_func<double>(const double& arg)
{
    std::cout << arg;
}
Here, some_func() can only be instansiated with T = float or T = double. (I realize in this case that overloads would be a much better choice, but I'm just trying to illustrate.) Is there anything akin to #compile_error as I used it above? Thanks!
Advertisement
This is the only way i know of for sending errors manually to the output window:

HERE!
Quote:Original post by GenuineXP
math::matrix<float, math::dim_static2<4, 4>, math::row_major, math::column_major> mat;
Wow...that looks very familiar :-|

If it's just the functionality you're after, the Configurable Math Library (linked in my signature) already does exactly what you've shown above (and I do mean exactly :).

Or, you could just look at the CML source to see how we handle compile-time errors. IIRC, it's fairly similar to the Boost compile-time macros; in any case, we use class names to generate (relatively) meaningful error messages indicating what exactly has gone wrong.

[Edit: It looks like you might be misusing the term '* major' there in one of your last two template arguments. Remember that 'majorness' only refers to layout in memory, not to whether the basis vectors of the matrix are stored in the rows or columns.]

[Edit 2: For various reasons we opted not to use Boost in our first pass at the CML. But, if you're writing your own code from scratch, you're probably best off just using the Boost macros directly as in SiCrane's example.]
BOOST_STATIC_ASSERT(boost::is_floating_point<T>::value);

Or

BOOST_STATIC_ASSERT((boost::is_same<float, T>::value || boost::is_same<double, T>::value));
@jyk: After you helped me so much with my matrix problems, I tried to pack the concepts of row/column major layout/vector notation into my own configurable classes. I started with a very non-template based approach, and it got very messy and difficult to use. Through some inspiration from the STL, I decided packing the data into template parameters was the solution and came up with this.

And, of course, after I started using these templates, I indeed happened to notice the link in your signature in the same thread you helped me in. :-) This was what lead me to introduce math::dim_static2 and math::dim_dynamic rather than having dimensions directly involved in the template parameters as I had before. I hope stealing this idea isn't a problem. I don't mean to copy; my real intention is to learn while making something useful. I doubt it'll ever become a real library, and certainly will never rival your CML. :-) Please let me know if this bothers you and I can just look at the CML code instead of playing with this stuff.

@SiCrane: Thanks for the example. I figured BOOST_*_ASSERT would be where I should look, but I didn't find anything specific enough when I searched (I'm impatient :-P ).
Quote:Original post by GenuineXP
Please let me know if this bothers you...
Oh, heck no :) I just wanted to make sure you were aware that there's already something available that's kind of similar to what you're doing.

This topic is closed to new replies.

Advertisement