如何避免重复模板专业化?

时间:2017-02-22 01:41:38

标签: c++

我有一些函数适用于由C库定义的类型。

类型为float_2,float_3,float_4,int32_2,int32_3,int32_4。

这些类型有一些共同点,一个名为size的字段。 对于float_2,size = 2. float_3,size = 3等。

现在我对每种类型都有模板专业化。

static void add_number(rapidjson::Value &target, const char* name, float_2 src, Document::AllocatorType& alloc)
{   
    std::ostringstream ss;
    ss << src.x << " " << src.y;
    std::string s(ss.str());
    target.AddMember(StringRef(name), s, alloc);
}

static void add_number(rapidjson::Value &target, const char* name, float_3 src, Document::AllocatorType& alloc)
{   
    std::ostringstream ss;
    ss << src.x << " " << src.y << " " << src.z;
    std::string s(ss.str());
    target.AddMember(StringRef(name), s, alloc);
}

能够做到以下几点肯定会很高兴:

template <typename T>
static void add_number(rapidjson::Value &target, const char* name, T src, Document::AllocatorType& alloc)
{   
    std::ostringstream ss;
    switch(src.size){
      case 2: ss << src.x << " " << src.y;
      case 3: ss << src.x << " " << src.y << " " << src.z;
      case 4: ss << src.x << " " << src.y << " " << src.z << " " << src.w;
    }
    std::string s(ss.str());
    target.AddMember(StringRef(name), s, alloc);
}

但这并不起作用,因为这些字段对于定义的所有类型都不存在。是否有一些C ++魔术模板语法可以让我避免专注于每一个案例?

2 个答案:

答案 0 :(得分:2)

我不确定这是否与单独打印,尺寸或任何其他专业要求有关。但是,我认为对于所提出的案例,最少的专业化是为不同的案例重载流媒体运营商。这看起来像这样:

std::ostream& operator<<(std::ostream &stream, const float_2 &vec)
{
    return stream << vec.x << ", " << vec.y;
}

std::ostream& operator<<(std::ostream &stream, const float_3 &vec)
{
    return stream << vec.x << ", " << vec.y << ", " << vec.z;
}

std::ostream& operator<<(std::ostream &stream, const float_4 &vec)
{
    return stream << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w;
}

template < typename T >
static void add_number(rapidjson::Value &target, const char* name, const T &src, Document::AllocatorType& alloc)
{   
    std::ostringstream ss;
    ss << src;
    std::string s(ss.str());
    target.AddMember(StringRef(name), s, alloc);
}

答案 1 :(得分:1)

你确实可以使用&#34;模板魔法&#34; to(从中删除函数模板)重载(set)。如果不超过十种不同的类型,我宁愿选择operator<<重载。

namespace detail
{

    template <class T, class = int> struct has_z : std::false_type { };
    template <class T> struct has_z <T, decltype((void)T::z, 0)> : std::true_type { };

    template <typename T>
    static auto foo_impl(T src)
        -> std::enable_if_t<!has_z<T>::value>
    {
        std::cout << "1: " << src.x << " " << src.y << "\n";
    }

    template <typename T>
    static auto foo_impl(T src)
        -> std::enable_if_t<has_z<T>::value>
    {
        std::cout << "2: " << src.x << " " << src.y << " " << src.z << "\n";
    }

}

template<class T>
void foo(T src)
{
    detail::foo_impl(src);
}

现在,您可以对包含fooxy成员的每种类型使用z

struct A { double x{ 1 }, y{ 2 }; };
struct B { double x{ 3 }, y{ 4 }, z{ 5 }; };

int main() {
    A a;
    B b;
    foo(a);
    foo(b);
    return 0;
}

打印

1 2
3 4 5