是否有可能得到一个模板来使用 class 和那个 class 的成员函数?
Is it possible to get a template to use a class and a member function of that class?
我正在尝试为使用大小函数和项目索引函数的通用对象创建一个 for_each
函数。但是我在语法上遇到了一些困难。
这是我目前所拥有的(从第 128 行开始):
class base1
{
protected:
std::vector<int> items;
public:
base1()
: items({1,2,3})
{
}
int GetCount() const
{
}
};
class base2 : public base1
{
public:
base2()
: base1()
{
}
int GetItem(int i) const
{
return items[i];
}
};
class derived : public base2
{
public:
derived()
: base2()
{
}
};
template <typename CONTAINER, typename CONTAINER_BASE1, typename CONTAINER_BASE2, typename SIZE, typename CONTAINED, typename FUNC>
void for_each(CONTAINER* container, SIZE (CONTAINER_BASE1::*GetSize)() const, CONTAINED (CONTAINER_BASE2::*GetItem)(SIZE) const, FUNC& body)
{
for (SIZE i = 0; i < container->*GetSize(); ++i)
{
body(container->*GetItem(i));
}
}
void fn()
{
derived x;
for_each(&x, &derived::GetCount, &derived::GetItem, [](int i){
++i;
});
}
现在,我收到来自 VC++ 2013 的错误消息:
1>d:\projects\test\test.cpp(169): error C2064: term does not evaluate to a function taking 0 arguments
1> d:\projects\test\test.cpp(180) : see reference to function template instantiation 'void for_each<derived,base1,base2,int,int,fn::<lambda_862ea397905775f7e094cde6fe9b462c>>(CONTAINER *,SIZE (__thiscall base1::* )(void) const,CONTAINED (__thiscall base2::* )(SIZE) const,FUNC &)' being compiled
1> with
1> [
1> CONTAINER=derived
1> , SIZE=int
1> , CONTAINED=int
1> , FUNC=fn::<lambda_862ea397905775f7e094cde6fe9b462c>
1> ]
1>d:\projects\test\test.cpp(171): error C2064: term does not evaluate to a function taking 1 arguments
关于问题是什么有什么想法吗?
你有两个错误。您通过非 const 左值引用获取函子 - FUNC& body
- 它不像 lambda 那样绑定到临时对象;这被一个允许此类绑定的可怕的 MSVC 扩展隐藏了。您应该按值(标准库通常采用的方式)、const 左值引用(如果复制很昂贵 and/or 身份很重要)或转发引用(如果身份很重要并且operator()
可以是非const
).
其次是运算符优先级。后缀函数调用运算符的优先级高于 .*
和 ->*
。 container->*GetSize()
是 container->*(GetSize())
;你想要 (container->*GetSize)()
.
我也不确定这个设计。提供一个统一的接口可能更好,并且简单地做,例如 container.size()
和 container.at(i)
,而不是使用这个痛苦的成员函数指针系统。
我正在尝试为使用大小函数和项目索引函数的通用对象创建一个 for_each
函数。但是我在语法上遇到了一些困难。
这是我目前所拥有的(从第 128 行开始):
class base1
{
protected:
std::vector<int> items;
public:
base1()
: items({1,2,3})
{
}
int GetCount() const
{
}
};
class base2 : public base1
{
public:
base2()
: base1()
{
}
int GetItem(int i) const
{
return items[i];
}
};
class derived : public base2
{
public:
derived()
: base2()
{
}
};
template <typename CONTAINER, typename CONTAINER_BASE1, typename CONTAINER_BASE2, typename SIZE, typename CONTAINED, typename FUNC>
void for_each(CONTAINER* container, SIZE (CONTAINER_BASE1::*GetSize)() const, CONTAINED (CONTAINER_BASE2::*GetItem)(SIZE) const, FUNC& body)
{
for (SIZE i = 0; i < container->*GetSize(); ++i)
{
body(container->*GetItem(i));
}
}
void fn()
{
derived x;
for_each(&x, &derived::GetCount, &derived::GetItem, [](int i){
++i;
});
}
现在,我收到来自 VC++ 2013 的错误消息:
1>d:\projects\test\test.cpp(169): error C2064: term does not evaluate to a function taking 0 arguments
1> d:\projects\test\test.cpp(180) : see reference to function template instantiation 'void for_each<derived,base1,base2,int,int,fn::<lambda_862ea397905775f7e094cde6fe9b462c>>(CONTAINER *,SIZE (__thiscall base1::* )(void) const,CONTAINED (__thiscall base2::* )(SIZE) const,FUNC &)' being compiled
1> with
1> [
1> CONTAINER=derived
1> , SIZE=int
1> , CONTAINED=int
1> , FUNC=fn::<lambda_862ea397905775f7e094cde6fe9b462c>
1> ]
1>d:\projects\test\test.cpp(171): error C2064: term does not evaluate to a function taking 1 arguments
关于问题是什么有什么想法吗?
你有两个错误。您通过非 const 左值引用获取函子 - FUNC& body
- 它不像 lambda 那样绑定到临时对象;这被一个允许此类绑定的可怕的 MSVC 扩展隐藏了。您应该按值(标准库通常采用的方式)、const 左值引用(如果复制很昂贵 and/or 身份很重要)或转发引用(如果身份很重要并且operator()
可以是非const
).
其次是运算符优先级。后缀函数调用运算符的优先级高于 .*
和 ->*
。 container->*GetSize()
是 container->*(GetSize())
;你想要 (container->*GetSize)()
.
我也不确定这个设计。提供一个统一的接口可能更好,并且简单地做,例如 container.size()
和 container.at(i)
,而不是使用这个痛苦的成员函数指针系统。