I have been looking at creating a synchroniser helper template class which is based on Herb Sutter's ideas of a wrapper class in this talk This does not work in msvc as is (unless we remove the brace initialisation) but when brace initialisation is removed then it's fine.
In clang/gcc (ubuntu 12.10, gcc4.7.2, clang (3.2) self built with libc++) it seems the private access modifier has to appear before the public: which seems a little strange.
The error in gcc is
error: ‘t_’ was not declared in this scope
and clang is
error: use of undeclared identifier 't_'
auto operator()(F f) const ->decltype(f(t_))
It may be a template/declytpe issue that I am not aware of and wonder if anyone can help with this one. (all compiled with relevant c++11 flags)
template <class T>
class Synchronised {
public:
Synchronised(T t = T{}) : t_{t} {}
template <typename F>
auto operator()(F f) const -> decltype(f(t_)) {
std::lock_guard<std::mutex> lock{mutex_};
return f(t_);
}
private: // place this before public: and this object compiles
mutable T t_;
mutable std::mutex mutex_;
};
Edit: Adding Johannes's ideas and full class in case anyone wants a cut and paste.
#include <future>
#include <iostream>
#include <thread>
#include <vector>
template <class T> T &self(T &t) { return t; }
template<typename T> struct Dependent { };
template<typename T>
class Synchronised : Dependent<T>{
public:
explicit Synchronised(T t = T()) : t_(t) {}
template<typename Functor>
auto operator()(Functor functor) const ->decltype(functor(self(*this).t_)) {
//auto operator()(Functor functor) const ->decltype(functor(this->t_)) {
std::lock_guard<std::mutex> lock(mutex_);
return functor(t_);
}
private:
mutable T t_;
mutable std::mutex mutex_;
};
int main() {
Synchronised<std::string> sync_string("Start\n");
std::vector<std::future<void>> futures;
}