I need to use std::call_once in my templatized singleton class but currently below sample code is not compiling :
std::once_flag flag;
class LifeTrackerHelper
{
public:
template<class T>
inline static int SetLongevity(std::unique_ptr<T>& pobj,unsigned int longevity = 0)
{
return 0;
}
};
template<class T>
class Singleton
{
public:
inline static T* getInstance()
{
static std::unique_ptr<T> ptr(new T());
std::call_once(flag,&LifeTrackerHelper::SetLongevity<T>,ptr);
//static int i = LifeTrackerHelper::SetLongevity<T>(ptr);
// if call_once is commented and above line uncommented this will work
return ptr.get();
}
};
class Test
{
public:
void fun()
{
std::cout<<"Having fun...."<<std::endl;
}
};
int main()
{
Singleton<Test>::getInstance()->fun();
}
So need help in understanding how to properly use std::call_once here.
Your problem is &LifeTrackerHelper::SetLongevity<T> is a function pointer expecting a unique_ptr and an unsigned int, but it only gets the one argument. While the actual function has a default value for the second argument, it needs both arguments when called by a function pointer.
You can fix it by passing another argument:
std::call_once(flag, &LifeTrackerHelper::SetLongevity<T>, ptr, 0);
Or you can wrap it in a lambda:
std::call_once(flag, [](std::unique_ptr<T>& p){ return LifeTrackerHelper::SetLongevity<T>(p); }, ptr);
According to cppreference, before C++17 the arguments to call_once will be copied or moved. So far, I haven't gotten any errors passing a unique_ptr, but it might be wise to use std::ref on it.
Related
I have a need to implement 2 functions inside a templated class, where both functions do similar things, but not everything is the same. My proposed solution was to use if constexpr on a single template function, and then have an alias for each function:
template <typename T>
class MyClass
{
private:
template <bool test>
void TestFunc()
{
if constexpr(test)
{
// Do something
}
else
{
// Do other stuff
}
}
public:
?????? TestTrue = TestFunc<true>;
?????? TestFalse = TestFunc<false>;
}
I'm trying to figure out what should go where the question marks are, so far using, auto and const auto have not worked. I want the user to be able to call TestTrue() and TestFalse() directly from an object of the class directly.
You could do:
void TestTrue() { TestFunc<true>(); }
void TestFalse() { TestFunc<false>(); }
I don't think there's a better way.
For completeness, here's the ugly way.
As mentioned in the comments, TestFunc is a member function, not a type, so if you want to reference an explicit specialization of it, you'll need to use a member function pointer. In our case, these will be pointers of the following type.
using MemberTestFunction = void (MyClass::*)();
We can then acquire pointers to the true and false specialization of TestFunc like so:
template <typename T>
class MyClass
{
// ...
constexpr static MemberTestFunction TestTrue = &MyClass::TestFunc<true>;
constexpr static MemberTestFunction TestFalse = &MyClass::TestFunc<false>;
};
If you're not familiar with pointers to member functions, the syntax for calling TestTrue and TestFalse may look rather bizarre. If you're inside a member function, you can invoke these functions either by using the ->* operator, or by using std::invoke (C++17) from <functional>:
template <typename T>
class MyClass
{
// ...
void foo() {
// Direct call with pointer.
(this->*TestTrue)();
// Call using std::invoke.
std::invoke(TestTrue, this);
}
};
Alternatively, outside of MyClass, these calls would look like the following.
MyClass<nullptr_t> x;
// Using type deducation.
(x.*decltype(x)::TestTrue)();
// Using fully qualified name.
(x.*MyClass<nullptr_t>::TestTrue)();
// Using std::invoke (with type deducation).
std::invoke(decltype(x)::TestTrue, x);
It goes without saying this this is a needlessly obscure way of accomplishing any otherwise simple task. I would not advocate using this technique over creating new functions (as HolyBlackCat suggested) or simply naming TestFunc<true>() and TestFunc<false>() explicitly at the call site.
Transform function TestFunc to functor:
#include <iostream>
template <typename T>
class MyClass
{
private:
template <bool test>
struct TestFunc
{
void operator()() {
if constexpr(test)
{
std::cout << "TestTrue\n";
}
else
{
std::cout << "TestFalse\n";
}
}
};
public:
TestFunc<true> TestTrue;
TestFunc<false> TestFalse;
};
int main()
{
MyClass<int> myClass;
myClass.TestTrue();
myClass.TestFalse();
}
Compiling my code that contains this class:
class Dessin
{
private:
vector<Figures*>T;
public:
void ajouteFigure(const Figures& f) const
{
for(auto element: T)
{
T.push_back(f);
}
}
};
yields an error:
[Error] no matching function for call to
'std::vector::push_back(const Figures&) const'
This is what I'm supposed to do in the main()
Dessin s;
s.ajouteFigure(Cercle(1.1));
Why wouldn't this work?
Assuming Cercle is a class name, you're trying to push a value where a pointer is expected.
To "fix" the error you should change your ajouteFigure prototype to accept Figures pointers and non-const this:
void ajouteFigure(Figures* f)
Then you should call it passing a pointer to a Figures object, i.e. created with a new expression:
s.ajouteFigure(new Cercle(1.1));
That being said, this code seems pointless. You're adding the pointer as many times as you have elements in the vector (which is always 0 in the example you provided).
Using raw pointers is also unadvised, you should use smart pointers like std::unique_ptr, although that would break the current code.
Consider this, less improper, example:
class Dessin
{
private:
vector<unique_ptr<Figures>> T;
public:
void ajouteFigure(unique_ptr<Figures> f)
{
T.push_back(move(f)); // just once
}
};
and at the call site:
Dessin s;
s.ajouteFigure(make_unique<Cercle>(1.1)); // C++≥14
or, if you can't use C++14:
Dessin s;
s.ajouteFigure(unique_ptr<Figures>(new Cercle{1.1}));
Just to add to this, I think you would be better to make it a template function and create the right object inside the function with arguments to the constructor passed as function parameters.
This way you don't have to create a std::unique_ptr or use new every time you call the function.
Here's a basic implementation:
class Dessin{
public:
template<typename T, typename ... Args>
void ajouteFigure(Args &&... args){
figures.emplace_back(new T(std::forward<Args>(args)...));
}
private:
std::vector<std::unique_ptr<Figures>> figures;
};
Then using the class is less error-prone:
int main(){
Dessin d;
d.ajouteFigure<Cercle>(1.1);
}
I am trying to implement a generic event handling system with templates, but I get an error at compile time when I try to add the function to a list.
error C2298: missing call to bound pointer to member function
class EventManager
{
public:
template <class OBJECT>
void subscribe(std::string eventName, OBJECT *obj, void(OBJECT::*newEvent)(Event))
{
(obj->*newEvent)(Event()); // I can call the event just fine if I execute it alone
abc.push_back(obj->*newEvent); // Error c2298 here
}
static EventManager* Get();
private:
std::vector<void(*)(Event)> eventsList;
};
And this is where I call it:
EventManager::Get()->subscribe("EventName", this, &TestClass::eventTest);
void ATideManager::eventTest(Event event)
{
//Test
}
I am quite new to C++ and templates, so I'm sure the solution is easy, but I don't understand why I can call the event but not add it to the vector. Do you know how I could possibly do that?
As the documentation for that error message says:
A pointer to member-function expression must call the member function.
In other words, you cannot store a pointer to member-function including the object on which to call it, for later use.
Here is a simpler example using names similar to yours:
struct Object
{
void f() {}
};
int main()
{
Object obj;
using member_function_pointer = void (Object::*)();
member_function_pointer ptr = &Object::f;
(obj.*ptr)();
(obj.*ptr); // error
}
And this makes a lot of sense. Your abc is probably a vector of pointers to member-function (or just a vector of function pointers); it cannot magically store an object along with each pointer in it.
Generally, pointers to member functions are not exactly the nicest, cleanest or best feature of C++, and the awful syntax renders every piece of code using it completely unreadable. Fortunately, C++11 introduced std::function and lambdas, which gives you a much better alternative:
#include <functional>
#include <iostream>
#include <string>
#include <vector>
struct Event
{
int i;
};
class EventManager
{
public:
void subscribe(std::string const& eventName,
std::function<void(Event const&)> event)
{
abc.push_back(event);
}
static EventManager& get()
{
static EventManager instance;
return instance;
}
void onEvent(Event const& event)
{
for (auto&& f : abc)
{
f(event);
}
}
private:
EventManager() {}
EventManager(EventManager const&) = delete;
EventManager& operator=(EventManager const&) = delete;
std::vector<std::function<void(Event const&)>> abc;
};
struct ATideManager
{
void f()
{
EventManager::get().subscribe("EventName",
[=](Event const& event) { eventTest(event); });
}
void eventTest(Event const& event)
{
std::cout << "eventTest: " << event.i << "\n";
}
};
int main()
{
ATideManager manager;
manager.f();
Event some_event{ 123 };
EventManager::get().onEvent(some_event);
}
I've also fixed your needless use of pointers where references can be used, and some const-correctness issues.
obj->*newEvent is invalid. A member function pointer can be used in this way only to call the pointed-to member function.
You can however use std::vector<std::function<void(Event)>> and
abc.push_back(std::bind(newEvent, obj, std::placeholders::_1);
std::bind reference
I need to instantiate a free template function (FTF) within a template class (TC). The FTF takes as a template parameter one of the template parameters of the TC. The TC also holds generic pointers to these FTF's, and these functions are called through the pointers.
The step of taking a pointer to a FTF is not enough to instantiate it, and I receive linker errors from the GCC toolchain. MSDN illustrates FTF specification as so -- however my instantion of the FTF is dependant on a template parameter of my TC, and therefore the FTF instantiation cannot be placed in free scope.
Is this possible ? I am attaching some basic generated code, the issue is in the constructor of the class test_service, where I assign the pointer of a free function into a custom container. I get a linker error telling me the free function cannot be found (uninstantiated). I know that specifying a call to the template function in the class somewhere will produce a instantiation, however I am only going to be making a call via a pointer.
#include "rpc_common.h"
#include <boost/cstdint.hpp>
namespace rubble { namespace rpc {
struct test_service_dummy_tag{};
template<typename T>
class test_service_skel
{
public:
bool Init() {}
bool TearDown() {}
bool test_one(TestRequest,TestResponse){};
private:
};
template<typename T_IMPL>
bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
{
return 0;
}
template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
class test_service
{
public:
test_service()
{
// uncomment the following two lines and a instantiation will occur.
// ClientRequest cr;
//test_service_test_one<T_IMPL>(m_impl,cr);
m_dispatch_table.SetEntry( Oid("test_one",0),(void *) & test_service_test_one<T_IMPL>);
}
bool Init() { return m_impl.Init(); };
bool TearDown() { return m_impl.TearDown(); };
private:
T_IMPL m_impl;
OidContainer<Oid,void *> m_dispatch_table;
};
} }
EDIT: self-contained minimal version
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T>
bool test_function()
{
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = (void *) & test_function<T>;
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
There is no problem iff you don't use a void*, i.e.: http://www.ideone.com/eRgUG
However, if you insist on storing the pointer in a void*, then you need to take the address using a specific function pointer first and then cast - e.g.
bool (*temp)() = &test_function<T>;
dispatch = reinterpret_cast<void*>(temp); // YUCK
This gives the compiler enough context to generate the address for you.
Ahh - just saw DeadMG's answer, the function to generate the void* is neater...
Your self-contained example wouldn't compile for me with a strange error about overloaded functions, when there is no overloading going on, with MSVC. I did, however, manage to work around it.
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T> void* to_void_pointer(T t) {
return reinterpret_cast<void*>(t);
}
template<typename T>
bool test_function()
{
return true;
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = to_void_pointer(&test_function<T>);
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
This compiles cleanly. I suspect that whatever behaviour you're seeing and I saw is a compiler error.
Suppose I have an autolocker class which looks something like this:
template <T>
class autolocker {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
~autolocker() {
lock->unlock();
}
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
T *lock;
};
Obviously the goal is to be able to use this autolocker with anything that has a lock/unlock method without resorting to virtual functions.
Currently, it's simple enough to use like this:
autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
but it is illegal to do:
autolocker lock(&my_lock); // this would be ideal
Is there anyway to get template type deduction to play nice with this (keep in my autolocker is non-copyable). Or is it just easiest to just specify the type?
Yes you can use the scope-guard technique
struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }
autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};
template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }
~autolocker() {
if(lock)
lock->unlock();
}
private:
autolocker& operator=(const autolocker&);
private:
mutable T *lock;
};
Then write a function creating the autolocker
template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}
typedef autolocker_base const& autolocker_t;
You can then write it like this:
autolocker_t lock = makelocker(&my_lock);
Once the const reference goes out of scope, the destructor is called. It doesn't need to be virtual. At least GCC optimizes this quite well.
Sadly, this means you have to make your locker-object copyable since you need to return it from the maker function. But the old object won't try to unlock twice, because its pointer is set to 0 when it's copied, so it's safe.
Obviously you can't get away with autolocker being a template, because you want to use it as a type, and templates must be instantiated in order to obtain types.
But type-erasure might be used to do what you want. You turn the class template into a class and its constructor into a member template. But then you'd have to dynamically allocate an inner implementation object.
Better, store a pointer to a function that performs the unlock and let that function be an instance of a template chosen by the templatized constructor. Something along these lines:
// Comeau compiles this, but I haven't tested it.
class autolocker {
public:
template< typename T >
autolocker(T *l) : lock_(l), unlock_(&unlock<T>) { l->lock(); }
~autolocker() { unlock_(lock_); }
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
typedef void (*unlocker_func_)(void*);
void *lock_;
unlocker_func_ unlock_;
template <typename T>
static void unlock(void* lock) { ((T*)lock)->unlock(); }
};
I haven't actually tried this and the syntax might be wrong (I'm not sure how to take the address of a specific function template instance), but I think this should be doable in principle. Maybe someone comes along and fixes what I got wrong.
I like this a lot more than the scope guard, which, for some reason, I never really liked at all.
I think jwismar is correct and what you want is not possible with C++. However, a similar (not direct analogue) construct is possible with C++0x, using several new features (rvalues/moving and auto variable type):
#include <iostream>
template <typename T>
class autolocker_impl
{
public:
autolocker_impl(T *l) : lock(l) {
lock->lock();
}
autolocker_impl (autolocker_impl&& that)
: lock (that.lock)
{
that.lock = 0;
}
~autolocker_impl() {
if (lock)
lock->unlock();
}
private:
autolocker_impl(const autolocker_impl&);
autolocker_impl& operator=(const autolocker_impl&);
private:
T *lock;
};
template <typename T>
autolocker_impl <T>
autolocker (T* lock)
{
return autolocker_impl <T> (lock);
}
struct lock_type
{
void lock ()
{ std::cout << "locked\n"; }
void unlock ()
{ std::cout << "unlocked\n"; }
};
int
main ()
{
lock_type l;
auto x = autolocker (&l);
}
autolocker is a class template, not a class. Your "this would be ideal" is showing something that doesn't make sense in C++.