C ++ recursive template specialization

I wrote a template template for an abstract container that should define numeric operators (unitary + and -, binary +, - and *) if it accepts a template parameter (that is, if it is a numeric type).

Then I would like to apply these numerical operations in containers of containers with numerical values ​​(and on containers of containers from containers with numerical values, etc.).

I wrote the following code. The marker (A)shows how I tried to solve the problem of recursive specialization.

template <typename T>
struct is_numeric : public std::is_arithmetic<T>{};

template <typename T> /* (A) */
struct is_numeric<GenericContainer<T>> : public std::is_arithmetic<T>{};


/* Classic generic container for non-numeric base types */
template <typename T, bool isNumeric=false>
class BaseContainer : public GenericContainer<T> {};

/* Numeric container: +,-,* operations for numeric base types */
template <typename T>
class BaseContainer<T, true> : public NumericContainer<T> {};

/* Arithmetic base types should map on numeric containers */
template <typename T>
class Container : public BaseContainer<T, is_numeric<T>::value> {};

Then in the test program I have the following statements:

/* Vector inherits from Container */
typedef Vector<int, 3> V3D;
ASSERT(is_numeric<int>::value);    /* # => OK */
ASSERT(is_numeric<double>::value); /* # => OK */
ASSERT(is_numeric<V3D>::value);    /* # => FAIL */

The first two statements work as expected.

+4
source share
4 answers

:

template <typename T>
struct is_numeric : public std::is_arithmetic<T>{};

template <template<class...> class Container, typename T, typename... Rest>
struct is_numeric<Container<T, Rest...>> : public is_numeric<T>{};

, .

+1

Boost enable_if :

template <class T, class Enable = void> 
struct is_numeric : public std::is_arithmetic<T> {};

template <class T>
struct is_numeric<T, typename enable_if<is_base_of<GenericContainer<T>, T> >::type>
            : public std::is_arithmetic<T> {};

SFINAE is_numeric, enable_if. , is_base_of is_base_of<Base, Derived>. Boost enable_if .

, , , , -:

template <template <class> class U, class T>
struct is_numeric<U<T>, typename enable_if<is_base_of<GenericContainer<T>, U<T> > >::type>
            : public std::is_arithmetic<T> {};

, :)

+1

: , .

, , . constexpr ( ):

// Basis
constexpr bool is_numeric_impl(...) { return false; }

template <typename T>
constexpr bool is_numeric(T const& t) { return is_numeric_impl(&t); }

// Specializations
template <typename T,
          typename = std::enable_if<std::is_arithmetic<T>::value>::type>
constexpr bool is_numeric_impl(T const*) { return true; }

template <typename T>
constexpr bool is_numeric_impl(GenericContainer<T> const*) {
    return is_numeric((T const*)nullptr);
}

, , ; .

+1

is_numeric , base.

template <typename T, size_t N>
struct is_numeric< Vector<T,N> > : is_numeric< GenericContainer<T> > // *
{};

Also note that the definition is_numericshould be the same as in the comment, and not in the question. That is, you want to determine is_numericfor the container in terms of whether the nested type is numeric or not (so that you can clear different layers).

0
source

All Articles