tags:

views:

143

answers:

3

Now that we know that Concepts is not part of C++0x, I am looking for methods to impose restrictions on types in template functions.

Here are two examples:

If we want to make sure that a given type is an integer, we can use:

template <class N> inline int f(const N n)
{
    if ((N)0.1 != 0)               // if type of N is floating-point
        err()

    ....
}

if we want to make sure that a given type is an unsigned integer, we can use:

template <class N> inline int f(const N n)
{
    if ((N)-1 < (N)1)              // if type of N is floating-point / signed-integer
        err()

    ....
}

I am looking for creative ways to check for additional restrictions, that will cause in failure in run-time, or better, in compile-time (without concepts and without RTTI).

Any suggestions?

+11  A: 

Your checks can be handled much better at compile-time by using type-traits.

The first:

STATIC_ASSERT(std::numeric_limits<N>::is_integer)

The second:

STATIC_ASSERT(not std::numeric_limits<M>::is_signed)

Have a look at the Boost Concept Check Library and at Boost.StaticAssert.

Konrad Rudolph
+2  A: 

You can approximate restricted function templates via extended SFINAE. Here's an example that actually compiles with GCC 4.4.1 in C++0x mode:

#include <iostream>
#include <type_traits>

#define REQUIRES(...) ,class=typename std::enable_if<(__VA_ARGS__)>::type

template <typename IntType
    REQUIRES( std::is_integral<IntType>::value )
>
inline IntType f(IntType n) {
    return n;
}

int main() {
    std::cout << f( 2) << '\n';
    // std::cout << f(3.1415) << '\n'; // won't work
}

The nice thing about SFINAE is that when template argument deduction fails the function template is just ignored and won't be part of the overload set. The example above exploits the fact that C++0x will support default template arguments for function templates. In good old C++98 it would look like this:

template <typename IntType>
inline
typename boost::enable_if_c<(
    std::numeric_limits<IntType>::is_integer
),IntType>::type f(IntType n) {
    return n;
}

Cheers, S

sellibitze
A: 

To easily check inheritance you can also do

template <typename T>
class MyClass
{
private:
  static ClassA *checkIfTIsA() { return (T *)NULL; }
};
rstevens