[英]Run different code for a class that has either an object or an array of objects as a member
I have a method that takes an object as parameter 我有一个方法,将对象作为参数
void fun(const Obj& obj)
Obj
can be defined in two different ways: Obj
可以用两种不同的方式定义:
struct Obj
{
Type x;
};
and 和
struct Obj
{
Type x[42];
};
I cannot modify the definitions of Obj
(ie I can't rename the classes). 我无法修改Obj
的定义(即我无法重命名类)。 Also, I can't modify the signature of fun
and I'd rather not use preprocessor directives inside of fun
. 此外,我不能修改的签名fun
,我宁可不使用内部预处理指令fun
。 Is there a way to use metaprogramming to make this compile and work regardless of which definition of Obj
is included: 有没有办法使用元编程来进行编译和工作,无论包含哪个Obj
定义:
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
}
? ? Is there a way to do it without C++11 features? 有没有办法在没有C ++ 11功能的情况下完成它?
You could pick a specialization of a template based on decltype(obj.x)
: 您可以根据decltype(obj.x)
选择模板的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);
}
Possible C++03 way is a member detector trait class that checks for existence of Type Obj::x
. 可能的C ++ 03方式是检查Type Obj::x
是否存在的成员检测器特征类。 This time, template parameter of impl
would be bool
so you can simply pass the result of the check: 这次, impl
模板参数将是bool
因此您可以简单地传递检查结果:
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);
}
This can be done by a second call to an implementation function fun_impl
that also takes obj.x
as an argument. 这可以通过第二次调用实现函数fun_impl
来完成,该函数也将obj.x
作为参数。 This function specializes to scalars or arrays by two overloads, the latter accepting a reference to an array, so maintaining the array size as well: 此函数通过两个重载专门用于标量或数组,后者接受对数组的引用,因此也保持数组大小:
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);
}
This works in C++03 and does not require any traits features or SFINAE. 这适用于C ++ 03,不需要任何特征功能或SFINAE。 See also live example , where the remaining parts use C++11 for convenience. 另请参见实例 ,其余部分使用C ++ 11以方便使用。
If obj
only contains x
, you can drop it as an argument from fun_impl
. 如果obj
只包含x
,则可以将其作为fun_impl
的参数fun_impl
。 I left it here for the more general case where obj
might have other members as well. 我把它留在这里是为了更一般的情况,其中obj
也可能有其他成员。
Note that fun
itself is given as a template here; 请注意, fun
本身在此处作为模板给出; I guess this is what you need to do anyway since you are dealing with different definitions of Obj
. 我想这是你需要做的事情,因为你正在处理不同的Obj
定义。
My suggestion is to use function overloading. 我的建议是使用函数重载。 You don't need metaprogramming/templates in your case: 在您的情况下,您不需要元编程/模板:
void fun(const Obj& obj)
{
impl(obj.x);
}
void impl(const Type& x){...}
void impl(Type x[]){...}
If Obj::x
is declared as Type x
then the first impl()
version will be called. 如果将Obj::x
声明为Type x
则将调用第一个impl()
版本。 And similarly in another case the second impl()
version will be called. 同样在另一种情况下,将调用第二个impl()
版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.