简体   繁体   中英

template class specialization enable_if and default values

Given the following

template <typename T, typename Enable=void>
struct test{};

template <typename T,
    typename std::enable_if< some_trait<T>::value >::type >
struct test{};

assuming some_trait<T>::value is true , enable_if<T>::type is void , and the specialization is selected. However, my query is related to the selection when the follow is the case.

template <typename T,
    typename std::enable_if_t< some_trait<T>::value,T>::type >
struct test{};

When a second non void template parameter for enable_if is provided for ::type , the unspecialized template is selected, even when some_trait<T>::value is true , as ::type is T instead of void , and so doesn't match the default value in the primary template.

My question is where in the standard is the ordering described for which template is chosen, and why is the instanciation test<T,void> considered as a better match then test<T,T> .

https://ideone.com/7v4TTS

full sample :

#include <iostream>
#include <type_traits>

template <typename T,typename Enable=void>
struct test
{
    const char* value = "Primary";
};

#if 1// toggle this

template <typename T>
struct test<T,typename std::enable_if< std::is_same<T,T>::value >::type > 
{
    const char* value = "Specialization";
};

#else

template <typename T>                                    
struct test<T,typename std::enable_if< std::is_same<T,T>::value,T >::type> 
{                                                          ///  ^    
    const char* value = "Specialization";
};

#endif

int main() {
    test<int> v;
    std::cout << v.value << std::endl;
    return 0;
}

In the first case you have the type

std::enable_if< true, void >

In the second case you have the type

std::enable_if< true, int >

std::enable_if< true, int >::type is int . It doesnt qualify a as type for typename Enable , which was requested to be void

test<int> v; is test<int, void> v; (thanks to default type).

test<int, int> v; would select your last specialization.

My question is where in the standard is the ordering described for which template is chosen, and why is the instanciation test<T,void> considered as a better match then test<T,T> .

[temp.class.spec.match] .

You wrote test<int> , which means that you didn't provide any template argument for the second parameter. Because it has a default parameter, it is chosen, so you actually have test<int, void> .

Now, according to the text linked above, the template parameters are matched to a specialization.

In the first case, the specialization is test<int, void> after evaluation, and so it is an exact match and chosen.

In the second case, the specialization is test<int, int> after evaluation, which is not an exact match and so the primary template is chosen instead of that specialization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM