是否可以获得一个模板来使用一个类和该类的成员函数?
Posted
技术标签:
【中文标题】是否可以获得一个模板来使用一个类和该类的成员函数?【英文标题】:Is it possible to get a template to use a class and a member function of that class? 【发布时间】:2015-02-25 17:02:39 【问题描述】:我正在尝试为使用大小函数和项目索引函数的通用对象创建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
关于问题所在有什么想法吗?
【问题讨论】:
【参考方案1】:你有两个错误。您通过非常量左值引用获取函子 - FUNC& body
- 它不会像 lambda 那样绑定到临时值;这被允许此类绑定的可怕 MSVC 扩展隐藏了。您应该按值(通常由标准库完成的方式)、通过 const 左值引用(如果复制代价高昂和/或身份很重要)或转发引用(如果身份很重要并且 @987654322 @ 可以是非const
)。
其次是运算符优先级。后缀函数调用运算符的优先级高于.*
和->*
。 container->*GetSize()
是 container->*(GetSize())
;你想要(container->*GetSize)()
。
我也不确定这个设计。提供一个统一的接口,并简单地做,例如container.size()
和container.at(i)
,可能比使用这种折磨人的指向成员函数的系统更好。
【讨论】:
哦,那不是很好。 :) 但我不是这个图书馆的制造者。base1
、base2
和derived
仅用于此处,不用于实际生产。谢谢。
顺便说一句,您指的 MSVC 扩展是什么?我应该只使用FUNC body
而不是FUNC const & body
吗?似乎与我使用FUNC& body
制作的另一个作品合作过。
@Adrian MSVC 允许非常量左值引用绑定到临时对象。标准库的风格是按值传递函子,但你也可以使用const FUNC&
或FUNC&&
(转发参考)。
啊,很高兴知道。但是,前向参考的意义是什么?我到底要搬什么?
@Adrian 当你想同时接受左值和右值,但身份很重要(所以不能通过值复制/传递),并且仿函数的operator()
可以是非常量(所以不能通过 const 引用)。 std::shuffle
是一个例子 - 它通过转发引用获取其 RNG。在这种情况下,它并没有真正用于转发; Scott Meyers 的旧“通用参考”术语可能更合适。以上是关于是否可以获得一个模板来使用一个类和该类的成员函数?的主要内容,如果未能解决你的问题,请参考以下文章