为具有对象或对象数组作为成员的类运行不同的代码

Run different code for a class that has either an object or an array of objects as a member

提问人:Luchian Grigore 提问时间:2/22/2014 最后编辑:Luchian Grigore 更新时间:2/22/2014 访问量:75

问:

我有一个将对象作为参数的方法

void fun(const Obj& obj)

Obj可以通过两种不同的方式定义:

struct Obj
{
   Type x;
};

struct Obj
{
   Type x[42];
};

我无法修改 的定义(即我无法重命名类)。另外,我无法修改 的签名,我宁愿不在 中使用预处理器指令。有没有办法使用元编程来编译和工作,而不管包含哪个定义:ObjfunfunObj

void fun(const Obj& obj)
{
   impl(obj); // executes some code if obj.x is an object
              // executes some other code if obj.x is an array 
}

?有没有办法在没有 C++11 功能的情况下做到这一点?

C++ 模板-元编程

评论

0赞 πάντα ῥεῖ 2/22/2014
抱歉,我已经监督了没有 C++11 功能的限制。无论如何,检查 std::is_array() 静态检查的解剖结构可能是个好主意,看看它如何为 c++03 标准实现(我很确定它应该是可能的)。

答:

2赞 jrok 2/22/2014 #1

您可以根据以下条件选择模板的专业化:decltype(obj.x)

template<typename T>
void impl(const Obj&);

template<> 
void impl<Type>(const Obj&) {}

template<>
void imp<Type[42]>(const Obj&) {}


void fun(const Obj& obj)
{
   impl<decltype(obj.x)>(obj);
}

可能的 C++03 方式是检查是否存在的成员检测器特征类。这一次,模板参数 这样你就可以简单地传递检查的结果:Type Obj::ximplbool

template<typename C>
struct has_Type_x {
    template<typename U, U>
    struct Check;

    typedef char(&yes)[1];
    typedef char(&no)[2];

    template<typename> static no test(...);
    template<typename U> static yes test(Check<Type U::*, &U::x>*);

    static const bool value = sizeof(test<C>(0)) == sizeof(yes);
};

template<bool> void impl(const Obj&);

template<>
void impl<true>(const Obj&) {}

template<>
void impl<false>(const Obj&) {
    std::cout << "arr";
}

void fun(const Obj& obj)
{
   impl< has_int_x<Obj>::value >(obj);
}

评论

0赞 Luchian Grigore 2/22/2014
说我不能使用 C++11?
1赞 jrok 2/22/2014
这需要更多的打字。Brb :)
0赞 Alex Antonov 2/22/2014 #2

我的建议是使用函数重载。在你的情况下,你不需要元编程/模板:

void fun(const Obj& obj)
{
   impl(obj.x);
}

void impl(const Type& x){...}
void impl(Type x[]){...}

如果声明为 ,则将调用第一个版本。同样,在另一种情况下,将调用第二个版本。Obj::xType ximpl()impl()

1赞 iavr 2/22/2014 #3

这可以通过第二次调用实现函数来完成,该函数也作为参数。此函数专门用于通过两个重载的标量或数组,后者接受对数组的引用,因此也保持数组大小:fun_implobj.x

template <typename Obj, typename T>
void fun_impl(const Obj& obj, const T& x) {}

template <typename Obj, typename T, size_t N>
void fun_impl(const Obj& obj, const T (&x)[N]) {}

template <typename Obj>
void fun(const Obj& obj)
{
   fun_impl(obj, obj.x);
}

这在 C++03 中有效,不需要任何特征特征或 SFINAE。另请参阅实时示例,为方便起见,其余部分使用 C++11。

如果仅包含 ,则可以将其作为参数从 中删除。我把它留在这里是为了更普遍的情况,那里可能还有其他成员。objxfun_implobj

请注意,它本身在这里作为模板给出;我想这是您无论如何都需要做的,因为您正在处理 .funObj

评论

0赞 Alex Antonov 2/22/2014
不幸的是,您的解决方案不符合要求,因为 OP“无法修改乐趣的签名”。
0赞 iavr 2/22/2014
@AlexAntonov 我的解决方案是指专门针对标量或数组。添加模板参数只是另一个建议。这两者是无关的。fun