Особенности реализации признаков - PullRequest
0 голосов
/ 20 марта 2019

Изначально у меня есть набор некоторых признаков StandardInfo и вспомогательный шаблон оболочки StandardTraits, полный статических методов, которые делают что-то с StandardInfo:

#include <iostream>
#include <type_traits>
#include <cstdint>

template <std::uint32_t Id>
struct StandardInfo
{ };

template <>
struct StandardInfo<1>
{
    using Field1 = std::integral_constant<std::uint32_t, 42>;
};

template <>
struct StandardInfo<2>
{
    using Field1 = std::integral_constant<std::uint32_t, 19>;
};

// and more StandardInfo specifications...



template <std::uint32_t Id>
struct StandardTraits
{  
    using Info = StandardInfo<Id>;
    static void DoFoo() { std::cout << Info::Field1::value; }
};



int main()
{
    StandardTraits<1>::DoFoo();
    return 0;
}

Предположим, мне нужно ввести еще одну черту нестандартного типа.Все специализации StandardInfo генерируются автоматически, и я не должен менять этот порядок вещей.Поэтому я должен представить черту NonStandartInfo.Поэтому мне нужна оболочка NonStandardTraits, содержащая те же методы, что и в StandardTraits.Оказывается, что StandardTraits и NonStandardTraits отличаются только псевдонимом типа Info.Копирование-вставка реализации кажется сомнительным, поэтому мне кажется, что мне нужно осуществить реализацию оболочки в виде TraitsImpl, а не изменять существующий код, который уже использует StandardTraits.

#include <iostream>
#include <type_traits>
#include <cstdint>

template <std::uint32_t Id>
struct StandardInfo
{ };

template <>
struct StandardInfo<1>
{
    using Field1 = std::integral_constant<std::uint32_t, 42>;
};

template <>
struct StandardInfo<2>
{
    using Field1 = std::integral_constant<std::uint32_t, 19>;
};

// and more StandardInfo specifications...

template <std::uint32_t Id>
struct NonStandardInfo
{ };

template <>
struct NonStandardInfo<1>
{
    using Field1 = std::integral_constant<int, -1>;
};

template <>
struct NonStandardInfo<2>
{
    using Field1 = std::integral_constant<int, -2>;
};

template <typename Info>
struct TraitsImpl
{
    static void DoFoo() { std::cout << Info::Field1::value; }
};

template <std::uint32_t Id>
struct StandardTraits: TraitsImpl<StandardInfo<Id> >
{  

};

template <std::uint32_t Id>
struct NonStandardTraits: TraitsImpl<NonStandardInfo<Id> >
{    
};


int main()
{
    StandardTraits<1>::DoFoo();
    NonStandardTraits<1>::DoFoo();
    return 0;
}

Но не раскрывает ли детали реализации (через публичное наследование)?Наследование частных и прокси-вызовов также выглядит глупо.Есть ли более элегантный подход?

...