mardi 26 février 2019

Question about SFINAE of class template and function template

I try to specialize the template (function or class) for STL containers. The standard I used is c++14.

For the template function, I try the code as following.

template<typename... Args>
using int_t = int;

template<typename T, int_t
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
> = 0>
void container_handler()
{
}

I think that if any type is not existed in "int_t", the template function will not be instantiated, but the compile errors are not happen when I invoke the template function as the following.

container_handler<int>();

However, I get the different result when use the class template.

template<typename... Args>
using int_t = int;

template<typename T , typename = int>
struct ContainerHandler;

template<typename T>
struct ContainerHandler<T, int_t
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
>>
{
};

The above code works, the compile errors is occurred when I instantiates the class template with the type who hasn't defined the special type or function.

ContainerHandler<int> handler1; //compile error
ContainerHandler<int, int> handler2; //compile error
ContainerHandler<vector<int>> handler3; //ok
ContainerHandler<vector<int>, int> handler4; //ok

The "int_t" here can be replaced by "void_t" in c++17. My question is why the SFINAE rule is different of the function template and class template. For the function template, I try another way and it works.

template<typename... Args>
struct type_container
{
    using int_t = int;
};

template<typename T, typename type_container
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
>::int_t = 0>
void container_handler()
{
}

container_handler<int>(); //compile error
container_handler<int, 0>(); //compile error
container_handler<vector<int>>(); //ok
container_handler<vector<int>, 0>(); //ok

I don't know what the difference between use "int_t" and "type_container::int_t".

Aucun commentaire:

Enregistrer un commentaire