SFINAE for class methods
От: koenjihyakkei Россия  
Дата: 10.01.19 13:38
Оценка:
Есть такой код:

template<class FooType>
class Foo
{

};

class Sr
{
    template<class T>
    typename std::enable_if<std::is_array<T>::value, bool>::type
        Func(T& val)
    {
        
    }

    template<class T>
    typename std::enable_if<!std::is_integral<T>::value && !std::is_array<T>::value, bool>::type
        Func(T& val)
    {
        
    }
};


Как можно специфицировать функцию Func конкретно для класса Foo?
Пробовал так:

template<class T>
typename std::enable_if<std::is_same<Foo, T>::value, bool>::type
    Func( T& val)
{
    
}

Но компилятор требует указания FooType у Foo. Хотя мне это не важно, главное специфицировать функцию для всех Foo независимо какой у них FooType.
Такое вообще возможно?

Спасибо заранее.
Re: SFINAE for class methods
От: σ  
Дата: 10.01.19 13:52
Оценка:
K>Как можно специфицировать функцию Func конкретно для класса Foo?

Никак. Foo это шаблон класса, а не класс.
Re: SFINAE for class methods
От: Chorkov Россия  
Дата: 10.01.19 13:59
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть такой код:


K>
K>template<class FooType>
K>class Foo
K>{

K>};

K>class Sr
K>{
K>    template<class T>
K>    typename std::enable_if<std::is_array<T>::value, bool>::type
K>        Func(T& val)
K>    {
        
K>    }

K>    template<class T>
K>    typename std::enable_if<!std::is_integral<T>::value && !std::is_array<T>::value, bool>::type
K>        Func(T& val)
K>    {
        
K>    }
K>};
K>


K>Как можно специфицировать функцию Func конкретно для класса Foo?

K>Пробовал так:

Дав варианта:

2) "просто перегрузка"
template<class T>
bool Func( Foo<T>& val )
{
    
}




1) определить is_Foo<...> (если нужно использовать это условие в сложных выражениях).

template <typename T>
struct is_Foo : std::false_type {};

template <typename T>
struct is_Foo< Foo<T> > : std::true_type {};

...


    template<class T>
    typename std::enable_if<!std::is_integral<T>::value && !std::is_array<T>::value && !is_Foo<T>::value  ,  bool>::type
        Func(T& val)
    {
        
    }

    template<class T>
    typename std::enable_if< is_Foo<T>::value, bool>::type
        Func( T& val)
    {
    
    }
Re: SFINAE for class methods
От: Constructor  
Дата: 10.01.19 14:09
Оценка: 2 (1)
Здравствуйте, koenjihyakkei, Вы писали:

K>Как можно специфицировать функцию Func конкретно для класса Foo?

K>Пробовал так:

K>
K>template<class T>
K>typename std::enable_if<std::is_same<Foo, T>::value, bool>::type
K>    Func( T& val)
K>{
    
K>}
K>

K>Но компилятор требует указания FooType у Foo. Хотя мне это не важно, главное специфицировать функцию для всех Foo независимо какой у них FooType.
K>Такое вообще возможно?

Тут нужен type trait is_specialization_of, который можно реализовать, например, так:
#include <type_traits>


namespace detail
{

    template <template <typename...> class Template>
    struct is_specialization_of
    {
        template <typename>
        struct type : std::false_type
        {
        };

        template <typename... Arguments>
        struct type<Template<Arguments...>> : std::true_type
        {
        };
    };

}    // namespace detail

template <typename Specialization, template <typename...> class Template>
using is_specialization_of = typename detail::is_specialization_of<Template>::template type<Specialization>;

Пример использования:
// ...

template <typename Type>
struct Foo
{
};

struct Bar
{
    template <typename Type>
    std::enable_if_t<is_specialization_of<std::decay_t<Type>, Foo>{}> Func(Type&& value)
    {
        (void)value;
        std::cout << "Bar::Func<Type>(Type&& value): overload for Foo template specialization" << std::endl;
    }

    template <typename Type>
    std::enable_if_t<!is_specialization_of<std::decay_t<Type>, Foo>{}> Func(Type&& value)
    {
        (void)value;
        std::cout << "Bar::Func<Type>(Type&& value): overload for other types" << std::endl;
    }
};
Re: SFINAE for class methods
От: sergii.p  
Дата: 10.01.19 14:19
Оценка: 3 (1)
Здравствуйте, koenjihyakkei, Вы писали:

#include <iostream>
using namespace std;

template< template<typename...> class Template, typename T >
struct is_instantiation_of : std::false_type {};
 template< template<typename...> class Template, typename... Args >
struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};

template<class FooType>
class Foo
{

};

class Sr
{
public:
    template<class T>
    typename std::enable_if<is_instantiation_of<Foo, T>::value, bool>::type
        Func( T val)
    {
        cout << "for Foo" << endl;
    }
    template<class T>
    typename std::enable_if<!is_instantiation_of<Foo, T>::value, bool>::type
        Func( T val)
    {
        cout << "for not Foo" << endl;
    }
};

int main() {
    Foo<int> foo;
    Sr sr;
    sr.Func(foo);
    sr.Func(1);
    return 0;
}
Re[2]: SFINAE for class methods
От: koenjihyakkei Россия  
Дата: 10.01.19 16:21
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>template< template<typename...> class Template, typename T >

SP>struct is_instantiation_of : std::false_type {};
SP> template< template<typename...> class Template, typename... Args >
SP>struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};

Супер! Работает как надо!
А где можно почитать, что тут происходит? Почему для class Foo выводится вторая версия? За счет чего это достигается? Что значит < Template, Template<Args...> > после is_instantiation_of? Это же вроде не частичная специализация..
Re[3]: SFINAE for class methods
От: sergii.p  
Дата: 10.01.19 16:44
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>А где можно почитать, что тут происходит? Почему для class Foo выводится вторая версия? За счет чего это достигается? Что значит < Template, Template<Args...> > после is_instantiation_of? Это же вроде не частичная специализация..


а почему вы думаете что это не частичная специализация? Подстановка Foo<int> оказывается более лучшей именно для второго варианта
struct is_instantiation_of< Foo, Foo<int> > : std::true_type {};

В моём понимании, это и есть частичная специализация.
По поводу, где почитать... Не знаю. Видимо надо курить Джосаттиса. Эта же реализация честно содрана со stackoverflow.
https://stackoverflow.com/questions/11251376/how-can-i-check-if-a-type-is-an-instantiation-of-a-given-class-template
https://stackoverflow.com/questions/15175829/c11-how-to-check-if-a-type-is-an-instantiation-of-a-given-class-template-of
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.