我有一些函数适用于由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 ++魔术模板语法可以让我避免专注于每一个案例?
答案 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);
}
现在,您可以对包含foo
,x
和y
成员的每种类型使用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