Я экспериментирую с сериализацией / десериализацией с шаблоном, и теперь что-то работает.Очевидно, что при его реализации я столкнулся со многими проблемами с сотнями журналов ошибок компилятора.Прежде чем расширять свою библиотеку, я хотел бы немного ее обезопасить, используя SFINAE (которую я до сих пор использовал редко) и static_asserts.
Чтобы больше не связываться с моей библиотекой, я тренируюсь в песочнице:
http://coliru.stacked -crooked.com / a / 9eb4eaefaac90fc0
Я хочу определить несколько предикатов:
- is_a_base для проверки объекта, производного от Base.
- is_insertable & is_extractable, чтобы проверить, были ли операторы >> и оператор << былиопределены для этого типа.</li>
Я хочу использовать эти предикаты как для специализации SFINAE, так и для static_assert.
#include <sstream>
#include <iostream>
//forward declaration
class Base;
//"Template typedef" to check predicates
template <typename T>
using is_a_Base = typename std::enable_if<std::is_base_of<Base, T>::value, void>::type;
template <typename T, typename is = std::istream>
using is_extractable = decltype (is{} >> T{});
template <typename T, typename os = std::ostream>
using is_insertable = decltype (os{} << T{});
//Test classes
class Base{
public:
std::string getStr(){ return "Base.getStr()";}
};
class Derived: public Base {};
class Other{};
//A template class with its specializations with SFINAE
template <typename T, typename Enable = void>
class C{
public:
static void f(T& o){
std::cout << "f<T> default !" << std::endl;
}
};
template<typename T>
class C<T, is_a_Base<T>>
{
public:
static void f (T& o)
{
std::cout << "f<is_a_A>() ! " << o.getStr() << std::endl;
}
};
template<typename T>
class C<T, is_insertable<T> >
{
public:
static void f (T& o)
{
std::cout << "f<is_insertable() ! " << o << std::endl;
}
};
template<typename T>
std::string g(T& ref)
{
//static_assert(is_a_Base<T>, "T is not a Base"); //can't figure out the syntax here
return ref.getStr();
}
int main(){
Base a;
Derived b;
int myint = 1;
std::string str="toto";
Other oops;
C<Base>::f(a);
C<Derived>::f(b);
C<int>::f(myint); //Not calling is_insertable ??
C<std::string>::f(str); //Not calling is_insertable ??
C<Other>::f(oops);
std::cout << "g:" << g(a) << std::endl;
//std::cout << "g:" << g(oops) << std::endl; //should be blasted by the static assert
}
Результаты:
f<is_a_A>() ! Base.getStr()
f<is_a_A>() ! Base.getStr()
f<T> default !
f<T> default !
f<T> default !
g:Base.getStr()
Пока что is_a_baseработает на SFINAE.Однако is_insertable не работает для переменных типа int и string?Также я не мог понять, как правильно повторно использовать предикат is_a_base в моем утверждении assert.
(Поскольку я ограничен кросс-компилятором, не поддерживающим C ++ 11, я не могу использовать преимущества от C++ 14 и далее.)