使用除专业之外的默认特征
Using default Traits apart from the specializations
我想做的是创建一个具有默认逻辑的通用特征 class,然后编写代码以专门化每个特定案例,仅包含与通用案例不同的内容。我的目标是消除代码重复并避免编写不必要的代码。
我举个例子:
int genericFunction(); // defined somewhere else
int specialFunction(); // defined somewhere else
template<int id>
struct IdTraits
{
using MyType = int;
using AnotherType = double;
static constexpr auto&& f = genericFunction;
};
template<>
struct IdTraits<1>
{
// Using MyType and AnotherType of IdTraits generic case [how?]
static constexpr auto&& f = specialFunction;
};
template<>
struct IdTraits<2>
{
// Using MyType and f of IdTraits generic case [how?]
using AnotherType = char;
};
template<int id, class Traits = IdTraits<id>>
struct General
{
void foo(int arg)
{
Traits::MyType myType;
Traits::AnotherType anotherType;
Traits::f(arg);
// Do stuff with myType and anotherType
}
};
你认为理论上可以做这样的事情吗?
是的。将您的通用案例放在基础 class:
namespace details
{
struct IdTraits_generic
{
using MyType = int;
using AnotherType = double;
static constexpr auto&& f = genericFunction;
};
}
template<int id> struct IdTraits : details::IdTraits_generic
{
};
template<> struct IdTraits<1> : details::IdTraits_generic
{
static constexpr auto&& f = specialFunction;
};
template<> struct IdTraits<2> : details::IdTraits_generic
{
using AnotherType = char;
};
您可以使用第二个 Trait 来完成这项工作。它的目的是检查当前 IdTrait<id>
中每个元素的存在,如果没有则设置默认的 type/function。
两种类型使用current experimental detection,函数使用member getF
:
template<int id>
struct MyIdTraits {
template <typename T> using MyType_t = typename T::MyType;
using MyType = std::experimental::detected_or_t<int, MyType_t, IdTraits<id>>;
template <typename T> using AnotherType_t = typename T::AnotherType;
using AnotherType = std::experimental::detected_or_t<double, AnotherType_t, IdTraits<id>>;
template <typename T, typename = decltype(T::f)>
static constexpr auto getF(int) { return T::f; }
template <typename T>
static constexpr auto getF(unsigned) { return genericFunction; }
static constexpr auto&& f = getF<IdTraits<id>>(42);
};
然后用这个替换你的特征:
template<int id, class Traits = MyIdTraits<id>>
struct General { ... };
我想做的是创建一个具有默认逻辑的通用特征 class,然后编写代码以专门化每个特定案例,仅包含与通用案例不同的内容。我的目标是消除代码重复并避免编写不必要的代码。
我举个例子:
int genericFunction(); // defined somewhere else
int specialFunction(); // defined somewhere else
template<int id>
struct IdTraits
{
using MyType = int;
using AnotherType = double;
static constexpr auto&& f = genericFunction;
};
template<>
struct IdTraits<1>
{
// Using MyType and AnotherType of IdTraits generic case [how?]
static constexpr auto&& f = specialFunction;
};
template<>
struct IdTraits<2>
{
// Using MyType and f of IdTraits generic case [how?]
using AnotherType = char;
};
template<int id, class Traits = IdTraits<id>>
struct General
{
void foo(int arg)
{
Traits::MyType myType;
Traits::AnotherType anotherType;
Traits::f(arg);
// Do stuff with myType and anotherType
}
};
你认为理论上可以做这样的事情吗?
是的。将您的通用案例放在基础 class:
namespace details
{
struct IdTraits_generic
{
using MyType = int;
using AnotherType = double;
static constexpr auto&& f = genericFunction;
};
}
template<int id> struct IdTraits : details::IdTraits_generic
{
};
template<> struct IdTraits<1> : details::IdTraits_generic
{
static constexpr auto&& f = specialFunction;
};
template<> struct IdTraits<2> : details::IdTraits_generic
{
using AnotherType = char;
};
您可以使用第二个 Trait 来完成这项工作。它的目的是检查当前 IdTrait<id>
中每个元素的存在,如果没有则设置默认的 type/function。
两种类型使用current experimental detection,函数使用member getF
:
template<int id>
struct MyIdTraits {
template <typename T> using MyType_t = typename T::MyType;
using MyType = std::experimental::detected_or_t<int, MyType_t, IdTraits<id>>;
template <typename T> using AnotherType_t = typename T::AnotherType;
using AnotherType = std::experimental::detected_or_t<double, AnotherType_t, IdTraits<id>>;
template <typename T, typename = decltype(T::f)>
static constexpr auto getF(int) { return T::f; }
template <typename T>
static constexpr auto getF(unsigned) { return genericFunction; }
static constexpr auto&& f = getF<IdTraits<id>>(42);
};
然后用这个替换你的特征:
template<int id, class Traits = MyIdTraits<id>>
struct General { ... };