I would like to define a nullary static template member function which would be (explicitly) specialized on pointer-to-data-member and could have, for each specialization, different return type.
It should return some detailed information about each attribute, hence I will call this method trait. The trait object type returned will be inspected by other templates, so this whole machinery must be available at compile-time.
So far I have something like this (broken code, of course):
class Foo{
// some data members
int a; std::string b; int c;
// how to declare generic template here?
// compile-time error should ensue if none of the specializations below is matched
// specialization for a (aTraitExpr is expanded from macro, so it is OK to repeat it)
template auto trait<&Foo::a>()->decltype(aTraitExpr){ return aTraitExpr; }
// specialization for b; the return type will be different than for trait<&Foo::a>
template auto trait<&Foo::b>()->decltype(bTraitExpr){ return bTraitExpr; }
};
// some code which queries the trait at compile-time
// e.g. supposing all possible trait types declare isSerializable
// which happens to be True for a and False for b
Foo* foo;
template<bool isSerializable> void doSerialization(...);
template void doSerialization<true>(...){ ... };
template void doSerialization<false>(...){ /* no-op */ };
doSerialization<Foo::trait<&Foo::a>()::isSerializable>(...); // -> doSerialization<true>(foo)
doSerialization<Foo::trait<&Foo::b>()::isSerializable>(...); // -> doSerialization<False>(...)
doSerialization<Foo::trait<&Foo::c>()::isSerializable>(...); // -> compile error, specialization Foo::trait<&Foo::c> not defined
Could get some hint on how to achieve this? (I am not trying to invent a new serialization system, I already use boost::serialization; there will be more information in each trait, this is just for an example why it is needed at compile-time).
EDIT: I was able to get something nearing what I want, it is shown at ideone.com. I gave up having trait<Foo::a>() (for now), so there is static function getTrait_a() which returns reference to modifiable type-traits, which are however partially fixed at compile-time (so that Foo::TraitType_a::flags works, for instance). Thanks to everybody who replied, unfortunately I can only pick one of the answers as “answer”.
It looks like you want several overloads instead of specializations. Unfortunately you don’t detail on what
xTraitExpris, but it seems it’s just a type that has a memberisSerializabledefined. I would probably go like thistrait(W<M>())is a dependent call. A dependent call does ADL at definition and instantiation time and unqualified lookup only at definition time. That’s whyWand the additionaltraitoverloads using it must be defined before thetraittype overloads instead of after them, or the result of resolution in the return type and body of the functions will be different since they are parsed at different times (bodies are late parsed after the class definition, and return types are parsed immediately).You can either make
traitaconstexprfunction and makexTraitExprbe a literal class with a constexpr constructor initializingisSerializableappropriately, or you could applydecltypeas follows