Я хотел бы определить нулевую статическую функцию-член шаблона, которая (явно) специализировалась бы на указателе на элемент данных и могла бы иметь для каждой специализации другой тип возврата.
Он должен возвращать подробную информацию о каждом атрибуте, поэтому я назову этот метод trait
. Возвращенный тип трейт-объекта будет проверяться другими шаблонами, поэтому весь этот механизм должен быть доступен во время компиляции.
Пока у меня есть что-то вроде этого (сломанный код, конечно):
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
Можно подсказать, как этого добиться? (Я не пытаюсь изобретать новую систему сериализации, я уже использую boost::serialization; в каждом трейте будет больше информации, это просто для примера, зачем это нужно во время компиляции).
РЕДАКТИРОВАТЬ: мне удалось получить что-то близкое к тому, что я хочу, это показано на на сайте ideone.com а>. Я отказался от trait<Foo::a>()
(на данный момент), поэтому есть статическая функция getTrait_a()
, которая возвращает ссылку на модифицируемые признаки типа, которые, однако, частично фиксируются во время компиляции (так что, например, Foo::TraitType_a::flags
работает). Спасибо всем, кто ответил, к сожалению, я могу выбрать только один из ответов как «ответ».