我有一些代码,其中非泛型lamba表达式具有局部静态变量:临界区的互斥锁.可以简化为:
int i = 0;
auto lambda = [&i](int &v)
{
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
/* critical section with v and i */};
}
Run Code Online (Sandbox Code Playgroud)
现在,在这个lambda表达式实现的关键部分可以逐字其他类型的比重用int &和我也喜欢如更换简单改变int与auto在声明符,就像这样:
auto lambda = [&i](auto &v)
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我这样做,lambda(int&)并且lambda(float&)将不再共享相同的本地静态变量,这将破坏关键部分中的锁定.
满足所有这些要求的代码中最简单的变化是什么:
一个可行的解决方案是用类模板方法替换lambda表达式,如下所示:
class Lambda
{
public:
Lambda(int &i) : i_(i) {}
template<class V>
void operator()(V &v)
{
std::lock_guard<std::mutex> lock(mutex_);
/* critical section with v and i_ */
};
private:
static std::mutex mutex_; …Run Code Online (Sandbox Code Playgroud) C++标准在注释14.7.2/12 [temp.explicit]中声明了以下内容:
通常的访问检查规则不适用于用于指定显式实例化的名称.[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是通常不可访问的私有类型或对象,模板可能是成员模板或成员函数通常无法访问. - 结束说明]
如果我可以实例化它,我希望可以使用模板.
我尝试使用gcc-4.8.2,当我访问显式命名类的私有成员时,我得到了预期的行为.但是,当我通过模板参数访问私有成员时,访问检查规则确实适用.这是gcc中的错误,还是我错过了什么?
在下面的代码中,'succeeded'和'failed'之间的唯一区别是前者通过'A'直接访问私有成员,而后者通过模板参数'T'访问它.编译器抱怨privateFoobar在该上下文中是私有的.
#include <iostream>
#include <string>
struct A
{
private:
std::string privateFoobar() {return "private foobar!";}
};
typedef std::string (A::*Foobar)();
template <class Type, Type value>
struct Access
{
static Type getValue() {return value;}
};
template <class T>
struct IndirectAccess
{
static Foobar succeeds() {return Access<Foobar, &A::privateFoobar>::getValue();}
static Foobar fails() {return Access<Foobar, &T::privateFoobar>::getValue();}
};
template class Access<Foobar, &A::privateFoobar>;
int main() {
std::cout << (A().*Access<Foobar,&A::privateFoobar>::getValue())() << std::endl;
std::cout << (A().*IndirectAccess<A>::succeeds())() << std::endl;
std::cout << (A().*IndirectAccess<A>::fails())() << std::endl; …Run Code Online (Sandbox Code Playgroud)