Initially, I have a set of some traits StandardInfo and an auxiliary wrapper template StandardTraits full of static methods doing something with info with 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;
}
Suppose I need to introduce another non-standard type trait. All of the StandardInfo specializations are automatically generated and I am not supposed to change that order of things. So I have to introduce NonStandartInfo trait. Therefore, I need NonStandardTraits wrapper containing same methods as in StandardTraits. It turns out that StandardTraits and NonStandardTraits differs only in Info type alias. Copy-pasting the implementation seems dubious, so it seems I need to carry out the wrapper implementation into kind of TraitsImpl and not to change existing code that already uses 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;
}
But doesn't it expose implementation details (via the public inheritance)? Inheriting private and proxying calls looks silly too. Is there any more elegant approach?
Aucun commentaire:
Enregistrer un commentaire