Есть такой код:
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
Здравствуйте, 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
Здравствуйте, 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
Здравствуйте, 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
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить