Check at compile time if a template type or multiset is specified, and the element type is arithmetic

I have a function called 'equal' that takes 2 parameters, each of which must be either std :: set or std :: multiset, and the type of the container element must be arithmetic (int, float, double ...). I want the compiler to report an error if the above 2 conditions are not satisfied.

Hope my code can work as follows:

int main(void)
{
    std::set<int> s1;
    std::set<int> s2;
    equal(s1, s2);    //  OK

    std::multiset<float> s3;
    std::multiset<float> s4;
    equal(s3, s4);    //  OK

    std::set<int> s5;
    std::multiset<int> s6;
    equal(s5, s6);    //  compile error

    std::set<int*> s7;
    std::set<int*> s8;
    equal(s7, s8);    //  compile error

    std::vector<int> s9;
    std::vector<int> s10;
    equal(s9, s10);    //  compile error

    return 0;
}

And now he can check if the element is an arithmetic type, as shown below:

template <class Container, class = typename std::enable_if<std::is_arithmetic<typename Container::value_type>::value>::type>
bool equal(const Container &container1, const Container &container2)
{
    return true;
}

But how to make sure that the container is installed or multi-network?

the compiler can support C ++ 11, for example vc2015 or gcc4.8

+4
2
template<template<class...>class Z, class T>
struct is_instance_of_template : std::false_type {};

template<template<class...>class Z, class...Ts>
struct is_instance_of_template<Z,Z<Ts...>> : std::true_type {};

template<class Container>
using value_type_t = typename Container::value_type;

template <class Container,
    std::enable_if_t<
        std::is_arithmetic<value_type_t<Container>>{}
        && (
            is_instance_of_template<std::set, Container>{}
            || is_instance_of_template<std::multiset, Container>{}
        )
    >* =nullptr
>
bool equal(const Container &container1, const Container &container2)
{
  static_assert( std::is_arithmetic<value_type_t<Container>>{},
    "Container must contain arithmetic values"
  );
  static_assert(
    is_instance_of_template< std::set, Container >{}
    || is_instance_of_template< std::multiset, Container >{},
    "Container must be a set or multiset"
  );
  return true;
}

static_assert - SFINAE. SFINAE , SFINAE - .

, enable_if_t<>* =nullptr , MSVC2015, . class=enable_if_t<>. enable_if_t<>* =nullptr, .

+2

is_set_or_multiset, std::set<...> std::multiset<...>:

template <typename>
struct is_set_or_multiset : std::false_type {};

template <typename... Ts>
struct is_set_or_multiset<std::set<Ts...>> : std::true_type {};

template <typename... Ts>
struct is_set_or_multiset<std::multiset<Ts...>> : std::true_type {};

enable_if:

template <class Container, 
          class = typename std::enable_if<
                                std::is_arithmetic<typename Container::value_type>::value
                             && is_set_or_multiset<Container>{}
                                >::type>
bool equal(const Container &container1, const Container &container2)
{
    return true;
}

wandbox

+12

Source: https://habr.com/ru/post/1671875/


All Articles