我想要做的是使用默认逻辑创建一个通用traits类,然后编写代码来专门化每个特定情况,只使用与通用情况不同的东西。我的目标是删除代码重复并避免编写不必要的代码。
我给你举个例子:
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
}
};
你认为理论上可以做这样的事吗?
答案 0 :(得分:1)
是。将您的通用案例放在基类中:
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;
};
答案 1 :(得分:1)
您可以使用第二个特性来完成这项工作。其目的是检查当前IdTrait<id>
内每个元素的存在,并设置默认类型/函数。
对这两种类型使用当前experimental detection,为该函数使用成员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 { ... };
<强> Demo 强>