I am experimenting on serialization/deserialization with template, and have now something working. Obviously, when implementing it, I ran into many troubles with hundreds of compiler error logs. Before extending my library further, I would like to secure it a bit, using SFINAE (which I only used scarcely so far) and static_asserts.
Not to mess up any further with my lib, I'm training in a sandbox :
http://coliru.stacked-crooked.com/a/9eb4eaefaac90fc0
I want to define a few predicates :
- is_a_base to check the object derives from Base.
- is_insertable & is_extractable to check if operator>> and operator<< have been defined for this type.
I want to be able to use those predicates for both SFINAE specialization and 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
}
Results :
f<is_a_A>() ! Base.getStr()
f<is_a_A>() ! Base.getStr()
f<T> default !
f<T> default !
f<T> default !
g:Base.getStr()
So far, is_a_base is working for SFINAE. However, is_insertable is not working for the int and string variables ? Also I could not figure out how to properly reuse the is_a_base predicate into my assert statement.
(Since I am constrained with a cross-compiler not supporting beyond C++11, I can't use benefits from C++14 and beyond.)
Aucun commentaire:
Enregistrer un commentaire