I have a variadic variant_callable class object that I want to use for a runtime polymorphism. Inside it uses a visitor pattern with std::variant.
However, I came by a rather strange behavior, that is object's destructor is called twice!.
#include <utility>
#include <variant>
#include <tuple>
namespace detail
{
template<typename... Impl>
class variadic_callable
{
public:
template<typename T>
constexpr explicit variadic_callable(T &&t) //
: varImpl_(std::forward<T>(t))
{}
variadic_callable(const variadic_callable &) = delete;
variadic_callable(variadic_callable &&) = delete;
template<typename... Args>
constexpr decltype(auto) operator()(Args &&...args) const
{
return std::visit(
[argsTuple = std::forward_as_tuple(args...)](const auto &visitor) {
return std::apply(
[&visitor](auto &&...args) {
return visitor(std::forward<decltype(args)>(args)...);
},
argsTuple);
},
varImpl_);
}
private:
std::variant<Impl...> varImpl_;
};
} // namespace detail
#include <string>
#include <iostream>
int main(int, char **)
{
struct callable
{
std::string str = "Long enough string to be allocated. Oceanic";
callable()
{
std::cout << "callable()" << std::endl;
}
void operator()(int i) const
{
std::cout << str << " " << i << '\n';
}
~callable()
{
std::cout << "~callable()" << std::endl;
}
};
{
std::cout << "expcected:\n";
const auto &c = callable();
c(815);
std::cout << "finished\n";
}
std::cout << '\n';
{
std::cout << "actual\n";
const auto &w = detail::variadic_callable<callable>{callable()};
w(815);
std::cout << "finished\n";
}
}
The output:
Program returned: 0
expcected:
callable()
Long enough string to be allocated. Oceanic 815
finished
~callable()
actual
callable()
~callable()
Long enough string to be allocated. Oceanic 815
finished
~callable()
https://godbolt.org/z/d849EaqbE
I guess an UB is in-place, but I can't spot it.
What I find the most peculiar is the fact that in the "actual" case std::string resources are not destroyed after the first destructor invocation!
variadic_callable's constructor is being passed an object of type callable. This is a temporary object that cannot be the same object as the one stored in the std::variant (no matter how it is passed).
The callable inside the std::variant must therefore be move-constructed from the passed temporary object. Both of these objects need to be eventually destroyed, requiring two calls to callable's destructor.
To prevent this you need to pass the arguments from which callable is supposed to be constructed to variadic_callable's constructor instead (here an empty list) and then pass these on to std::variants in-place constructor, i.e.
template<typename T, typename... Args>
constexpr explicit variadic_callable(std::in_place_type_t<T> t, Args&&... args) //
: varImpl_(t, std::forward<Args>(args)...)
{}
called as
detail::variadic_callable<callable>{std::in_place_type<callable>};
Here I copied std::variant's constructor design for the in-place overload.
Related
I am trying to make a factory function that will be able to create objects derived from a base class using different constructors based on the given parameters. With some help from other posts here I have been able to make an example that works for a constructor that takes no parameters, but I cannot find a solution for multiple constructors.
I have the following:
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <functional>
using namespace std;
class BaseObject {
public:
BaseObject(){cout<<"BaseObject def constructor\n";};
BaseObject(int type){cout<<"BaseObject non-def constructor\n";}
virtual ~BaseObject() = default;
virtual string name() = 0;
};
class Object1 : public BaseObject
{
public:
Object1(){cout<<"Object1 def constructor\n";};
Object1(int type){cout<<"Object1 non-def constructor\n";}
virtual string name() override
{
return "I am Object1";
}
};
class Object2 : public BaseObject
{
public:
Object2(){cout<<"Object2 def constructor\n";};
Object2(int type){cout<<"Object2 non-def constructor\n";}
virtual string name() override
{
return "I am Object2";
}
};
struct Factory {
public:
typedef std::map<std::string, std::function<std::unique_ptr<BaseObject>()>> FactoryMap;
template<class T>
static void register_type(const std::string & name) {
getFactoryMap()[name] = [](){ return std::make_unique<T>(); };
}
static std::unique_ptr<BaseObject> get_object(const std::string name) {
return getFactoryMap()[name]();
}
static std::unique_ptr<BaseObject> get_object(const std::string name, int type) {
return getFactoryMap()[name](type);
}
// use a singleton to prevent SIOF
static FactoryMap& getFactoryMap() {
static FactoryMap map;
return map;
}
};
int main()
{
Factory::register_type<Object1>("Object1");
Factory::register_type<Object2>("Object2");
// make Object1 using default constructor
std::unique_ptr<BaseObject> o1 = Factory::get_object("Object1");
// make Object2 using non-default constructor
std::unique_ptr<BaseObject> o2 = Factory::get_object("Object2", 1);
std::cout << o1->name() << std::endl;
std::cout << o2->name() << std::endl;
std::cout << "exit" << std::endl;
return 0;
}
Both Object1 and Object2 have two constructors (it is simplified, in practice the one with the parameter will get some saved data) and Factory has two versions of get_object() each with the name of the object to be created and the corresponding additional parameters.
The problem with the second get_object
static std::unique_ptr<BaseObject> get_object(const std::string name, int type) {
return getFactoryMap()[name](type);
}
is that the call to the constructor inside passes type parameter, but the type of the function (as defined by typedef FactoryMap) has no parameters (std::function<std::unique_ptr<BaseObject>()>).
I explored variadic templates but was not able to figure out how it should be done. One of the helpful post was this one, unforunately it does not have a full working code example.
The problem is really hard in the general case as C++ lacks reflection. It can be solved however, in the assumption that the set of available constructors is fixed for a given factory. That is if you’re fine with defining your factory like using Factory = BaseFactory<BaseObject, void(), void(int)>; it is possible albeit requires black magic more templates. (using X = Y is the new, sane form of typedef Y X, and ret(args) is a function type [not a pointer but function itself; used like void, only in pointers and templates]). For example:
template <typename Base, typename Constructor>
struct Subfactory;
template <typename Base, typename... Args>
struct Subfactory<Base, void(Args...)> {
using constructor_type = std::unique_ptr<Base>(Args&&...);
template <typename Type>
static std::unique_ptr<Base> construct(Args&&...args) {
return std::make_unique<Type>(std::forward<Args>(args)...);
}
};
template <typename Base, typename... Constructors>
struct BaseFactory {
public:
using ConstructorList = std::tuple<typename Subfactory<Base, Constructors>::constructor_type *...>;
inline static std::map<std::string, ConstructorList> types;
template<class T>
static void register_type(const std::string & name) {
types[name] = ConstructorList{Subfactory<Base, Constructors>::template construct<T>...};
}
template <typename... Args>
static std::unique_ptr<Base> make_object(const std::string name, Args&&...args) {
const ConstructorList &type = types[name];
auto constructor = std::get<std::unique_ptr<Base>(*)(Args&&...)>(type);
return constructor(std::forward<Args>(args)...);
}
};
using Factory = BaseFactory<BaseObject, void(), void(int)>;
int main()
{
Factory::register_type<Object1>("Object1");
Factory::register_type<Object2>("Object2");
// make Object1 using default constructor
std::unique_ptr<BaseObject> o1 = Factory::make_object("Object1");
// make Object2 using non-default constructor
std::unique_ptr<BaseObject> o2 = Factory::make_object("Object2", 1);
std::cout << o1->name() << std::endl;
std::cout << o2->name() << std::endl;
std::cout << "exit" << std::endl;
return 0;
}
Explanation
template <typename Base, typename Constructor>
struct Subfactory;
template <typename Base, typename... Args>
struct Subfactory<Base, void(Args...)> {
using constructor_type = std::unique_ptr<Base>(Args&&...);
template <typename Type>
static std::unique_ptr<Base> construct(Args&&...args) {
return std::make_unique<Type>(std::forward<Args>(args)...);
}
};
This is a helper to unpack a function type. Specifically, the partial specialization matches all usages of the form Subfactory<any type, void(anything here)>, filling Args... with that “anything”.
Now, the factory itself.
template <typename Base, typename... Constructors>
struct BaseFactory {
Here, Constructors... is for the list of constructor signatures
using ConstructorList = std::tuple<typename Subfactory<Base, Constructors>::constructor_type *...>;
For each element C of Constructors..., this extracts the type Subfactory<Base, C>::constructor_type *, and defines ConstructorList as a tuple of all these types.
inline static std::map<std::string, ConstructorList> types;
A nice, C++17-only (but note that make_unique is C++17 too) replacement for getFactoryMap. Optional, your getFactoryMap is equally usable.
template<class T>
static void register_type(const std::string & name) {
types[name] = ConstructorList{Subfactory<Base, Constructors>::template construct<T>...};
This instantiates Subfactory<Base, C>::construct<T> for each C from Constructors... and makes ConstructorList passing (pointers to) these functions as arguments.
template <typename... Args>
static std::unique_ptr<Base> make_object(const std::string name, Args&&...args) {
const ConstructorList &type = types[name];
auto constructor = std::get<std::unique_ptr<Base>(*)(Args&&...)>(type);
return constructor(std::forward<Args>(args)...);
This gets the “type info” (constructor list) from the map, then gets appropriate constructor [wrapper] from the tuple (based on the received arguments), and calls it.
using Factory = BaseFactory<BaseObject, void(), void(int)>;
Here, Factory is defined as a factory of BaseObject supporting constructors with no arguments and with single int argument.
Note that this solution is not perfect. It requires good match of arguments given to the factory with the arguments it supports; no overloading resolution takes place. Supporting that is likely possible but requires more complicated tricks.
Update: here is a similar solution but with proper overload resolution:
/// A wrapper over single constructor of a single type.
/// #param Base is the common type
/// #param Constructor is a function type denoting the constructor signature. It must have the form `void(constructor arguments)`
template <typename Base, typename Constructor>
struct Subfactory;
/// The only specialization of #c Subfactory
template <typename Base, typename... Args>
struct Subfactory<Base, void(Args...)> {
/// The pointer to the constructor wrapper.
std::unique_ptr<Base> (*constructor)(Args&&...args);
/// The outer constructor wrapper. Unlike #c constructor which is a variable, this one is a function thus can participate in overload resolution.
std::unique_ptr<Base> construct(Args&&...args) {
return constructor(std::forward<Args>(args)...);
}
/// A factory factory. Returns an instance able to construct an object of type #p Type, but only with a constructor accepting #p Args as arguments.
template <typename Type>
static Subfactory metafactory() {
/// The constructor wrapper (written as a lambda for compactness)
return {[](Args&&...args) -> std::unique_ptr<Base> {
return std::make_unique<Type>(std::forward<Args>(args)...);
}};
}
};
/// The generic factory.
/// #param Base is the common type. Objects are returned as pointers to that type
/// #param Constructors are function types denoting the constructor signatures. Each must have the form `void(constructor arguments)`, and they must all be distinct
template <typename Base, typename... Constructors>
struct BaseFactory {
public:
/// A wrapper on constructor list of a single type.
/// It inherits one #c Subfactory for each constructor signature from #c Constructors.
/// Could also hold additional information, if necessary.
struct TypeInfo: public Subfactory<Base, Constructors>...
{
/// Another factory factory. Returns an instance able to construct an object of type #p Type with any supported constructor.
template <typename Type>
static TypeInfo metafactory() {
return TypeInfo{
Subfactory<Base, Constructors>::template metafactory<Type>()...
};
}
/// Brings *all* constructor wrappers in the scope so that #c construct names them all, as overloaded functions.
using Subfactory<Base, Constructors>::construct...;
};
inline static std::map<std::string, TypeInfo> types;
template<class Type>
static void register_type(const std::string & name) {
types[name] = TypeInfo::template metafactory<Type>();
}
template <typename... Args>
static std::unique_ptr<Base> make_object(const std::string name, Args&&...args) {
return types[name].construct(std::forward<Args>(args)...);
}
};
/// A factory of #c BaseObject subclasses, supporting constructors taking nothing or a single int.
using Factory = BaseFactory<BaseObject, void(), void(int)>;
int main()
{
Factory::register_type<Object1>("Object1");
Factory::register_type<Object2>("Object2");
// make Object1 using default constructor
std::unique_ptr<BaseObject> o1 = Factory::make_object("Object1");
// make Object2 using non-default constructor
std::unique_ptr<BaseObject> o2 = Factory::make_object("Object2", 1);
// make Object2 using overload resolution of a non-default constructor
std::unique_ptr<BaseObject> o3 = Factory::make_object("Object2", 'c');
std::cout << o1->name() << std::endl;
std::cout << o2->name() << std::endl;
std::cout << o3->name() << std::endl;
std::cout << "exit" << std::endl;
return 0;
}
Instead of storing function pointers in a tuple, a special type, TypeInfo, is used. One pointer is stored in each its base class, all of which are Subfactory but with different template arguments. Each Subfactory defines a construct function with appropriate arguments, and TypeInfo inherits them all and makes them all visible, thus subject to overload resolution like original constructors themselves.
Inspired by the answer by #numzero, I finally adopted a solution that uses less magic/templates and thus it looks more elegant to me. This solution works for constructors having fields of complex types, on the other hand it is limited by a requirement of all BaseObject descendants to have the same set of constructors (but that was the idea from the start):
#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <unordered_map>
using namespace std;
class BaseObject {
public:
virtual ~BaseObject() = default;
virtual string name() {
return "I am BaseObject";
}
};
class Object1 : public BaseObject
{
public:
Object1(const int i){cout<<"Object1 int constructor\n";}
Object1(const std::string s){cout<<"Object1 string constructor\n";}
Object1(const std::vector<double> params){cout<<"Object1 vector constructor\n";}
virtual string name() override
{
return "I am Object1";
}
};
class Object2 : public BaseObject
{
public:
Object2(const int i){cout<<"Object2 int constructor\n";}
Object2(const std::string s){cout<<"Object2 string constructor\n";}
Object2(const std::vector<double> params){cout<<"Object2 vector constructor\n";}
virtual string name() override
{
return "I am Object2";
}
};
using constructor1_t = std::function<std::unique_ptr<BaseObject>(const int)>;
using constructor2_t = std::function<std::unique_ptr<BaseObject>(const std::string s)>;
using constructor3_t = std::function<std::unique_ptr<BaseObject>(const std::vector<double>)>;
using constructors_t = std::tuple<constructor1_t, constructor2_t, constructor3_t>;
using constructors_map_t = std::unordered_map<std::string, constructors_t>;
template <class T>
std::function<constructors_t()> object_constructors = [](){
return constructors_t{
[](const int i){return std::make_unique<T>(i); },
[](const std::string s){return std::make_unique<T>(s); },
[](const std::vector<double> v){return std::make_unique<T>(v); }
};
};
constructors_map_t constructors_map = {
{"Object1", object_constructors<Object1>()},
{"Object2", object_constructors<Object2>()}
};
int main()
{
int i = 12;
std::string s = "abc";
std::vector<double> v(4, 0.0);
auto c1 = constructors_map["Object1"];
std::unique_ptr<BaseObject> o1 = std::get<0>(c1)(i);
std::unique_ptr<BaseObject> o2 = std::get<1>(c1)(s);
std::unique_ptr<BaseObject> o3 = std::get<2>(c1)(v);
std::cout << o1->name() << std::endl;
std::cout << o2->name() << std::endl;
std::cout << o3->name() << std::endl;
std::cout << "----" << std::endl;
auto c2 = constructors_map["Object2"];
std::unique_ptr<BaseObject> o4 = std::get<0>(c2)(i);
std::unique_ptr<BaseObject> o5 = std::get<1>(c2)(s);
std::unique_ptr<BaseObject> o6 = std::get<2>(c2)(v);
std::cout << o4->name() << std::endl;
std::cout << o5->name() << std::endl;
std::cout << o6->name() << std::endl;
return 0;
}
Let's say I declare a thread with the following code:
#include <thread>
#include <iostream>
void printStuff(const char* c, long x) {
std::cout << x << " bottles of " << c << " on the wall\n";
}
int main()
{
std::thread t(printStuff, "beer", 900000000);
t.join();
}
How are the arguments printStuff, "beer," and 900000000 stored in the thread?
I know they are using a variadic template, where you first pass in a function and then a parameter pack of arguments. I am confused on how they forward all these template arguments, and then somehow call the inputted function with all the arguments when join or detach is called.
std::function has similar functionality where when you call std::bind it will store a function and its arguments inside the object, and then when you call the std::function object it will just execute the bound function with its arguments.
I am basically trying to implement my own version of std::function, for my own edification. I am curious how in C++ you would go about storing a function with a bunch of arbitrary parameters inside an object, and then having a method that would call the function with the passed in arguments.
I have looked at both the thread and std::function class, and both seem to be using tuples in some way to store their arguments. In a declaration of a tuple you have to specify what types you are storing in it:
std::tuple<int, std::string> tup;
How do std::function and thread get around this by storing their variadic arguments in tuples? Furthermore, how do they retrieve the function and call it with all of the arguments?
I am basically trying to implement my own version of std::function, for my own edification. I am curious how in C++ you would go about storing a function with a bunch of arbitrary parameters inside an object, and then having a method that would call the function with the passed in arguments.
std::function is a beast of a class so I won't pretend that this is anywhere close to as complete. std::function uses type erasure and small object optimization but I'll use polymorphism and store a base class pointer to a semi-anonymous implementation of a function wrapper to show how it can be done. I say semi-anonymous because it actually has a name, but it's defined locally inside the function that instantiates it. Storing the pointer (or the empty state) will be done in a std::unique_ptr<funcbase>.
The goal, as I've understood it, is to create a class with this basic interface:
template <class R, class... Args>
class fn_with_args<R(Args...)> {
public:
template <class F> fn_with_args(F&& f, Args&&... args);
R operator()();
};
That is, we need instances of fn_with_args<R(Args...)> to be able to store function pointers / functors that when invoked with the stored arguments returns R.
#include <functional>
#include <memory>
#include <tuple>
template <class> class fn_with_args; // not implemented
template <class R, class... Args>
class fn_with_args<R(Args...)> {
// an abstract base for cloneable function objects with an operator()() to call
struct funcbase {
virtual ~funcbase() = default;
virtual std::unique_ptr<funcbase> clone() const = 0;
virtual R operator()() = 0;
};
public:
// create empty "fn_with_args":
fn_with_args() noexcept = default;
fn_with_args(std::nullptr_t) noexcept {};
// copy ctor - if store contains a pointer to a funcbase,
// let it clone itself
fn_with_args(const fn_with_args& other) :
store(other.store ? other.store->clone() : nullptr) {}
// copy assignment
fn_with_args& operator=(const fn_with_args& other) {
if(this != &other) *this = fn_with_args(other); // copy+move
return *this;
}
// moving can be done by default:
fn_with_args(fn_with_args&& other) noexcept = default;
fn_with_args& operator=(fn_with_args&& other) noexcept = default;
// constructing and storing arguments
template <class F>
fn_with_args(F&& f, Args&&... args) {
// the semi-anonymous implementation that inherits from funcbase
// and stores both the function and the arguments:
struct funcimpl : funcbase {
funcimpl(F&& f, Args&&... a)
: func{std::forward<F>(f)}, args{std::forward<Args>(a)...} {}
// cloning via a base class pointer:
std::unique_ptr<funcbase> clone() const override {
return std::make_unique<funcimpl>(*this);
}
// the operator that will call `func` with the stored arguments:
R operator()() override { return std::apply(func, args); }
F func; // the actual function/functor
std::tuple<Args...> args; // and the stored arguments
};
// create and store an instance of the above semi-anonymous class:
store = std::make_unique<funcimpl>(std::forward<F>(f),
std::forward<Args>(args)...);
}
// The call interface. It'll dereference `store` and then call it which
// will call the overridden operator()() in the semi-anonymous `funcimpl`:
R operator()() {
if(store) return (*store)();
throw std::bad_function_call();
}
private:
std::unique_ptr<funcbase> store;
};
Example usage:
#include <iostream>
double foo(int x) {
return x * 3.14159;
}
int main() {
fn_with_args<int(double)> f1([](double d) -> int { return d; }, 3.14159);
std::cout << f1() << '\n';
fn_with_args<void()> f2; // create empty
//f2(); // would throw "bad_function_call" since it is "empty"
// populate it
f2 = fn_with_args<void()>([]{ std::cout << "void\n"; });
f2();
// call regular function:
fn_with_args<double(int)> f3(foo, 2);
std::cout << f3() << '\n';
// example with capture:
int v = 123;
f1 = fn_with_args<int(double)>([v](double d) -> int { return v * d; }, 3.14159);
std::cout << f1() << '\n';
// copying:
auto f11 = f1;
std::cout << f11() << '\n'; // calling the copy
}
Demo
you should store the params in std::tuple and invoke them using std::apply
#include <functional>
#include <tuple>
#include <vector>
template <class R>
class Function_Wrapper {
public:
template <typename Callable, typename... Args>
Function_Wrapper(Callable&& callable, Args&&... args)
: fn_([=, args = std::make_tuple(std::forward<Args>(args)...)]() {
return std::apply(callable, args);
}) {}
decltype(auto) run() {
// call our callable with the passed in arguments
return fn_();
}
decltype(auto) operator()() { return run(); }
private:
std::function<R()> fn_;
};
int add(int a, int b) { return a + b; }
int main() {
std::vector<Function_Wrapper<int>> f{{&add, 9, 30}, {&add, 1, 2}};
return f[0].run() + f[1]();
}
Here in Compiler Explorer
I'm working on a mechanism for creating "safe" callbacks, that won't cause undefined behavior when called after their parent object has been destroyed. The class should be generic enough to be able to wrap any callback, with void(...) callbacks simply being executed or not, depending on the status of the object that they are bound to, and callbacks that return a value returning a boost::optional with the returned value, if executed, or boost::none if not executed.The implementation is almost complete, but there are 2 things that make me worried that I don't fully understand my code...
If line 19 is uncommented and 18 commented out, the template won't compile - is this merely a syntactic problem that can be solved, or am I trying to use the result_of mechanism incorrectly (does the std::forward there change the semantics or is it superfluous?)
If line 88 is uncommented and 89 commented out, the compilation results in failure due to ambiguousness of the function call to fun, which I don't quite understand - it seems to me that fun(int&&) is an exact match, so why does the compiler complain of ambiguousness with fun(int) version?
If there are other subtle (or gross) errors, please comment as well.
Thanks.
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <memory>
#include <boost/optional.hpp>
template<class Func>
class SafeCallback
{
public:
SafeCallback(std::shared_ptr<bool> guard, const Func& callback)
: guard_(guard)
, callback_(callback)
{}
template<class... Args>
// auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(std::forward<Args>(args)...)>::type>::value, // won't compile with: 19:91: error: invalid use of template-name 'std::result_of' without an argument list
auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(Args...)>::type>::value,
void>::type
{
std::cout << "trying void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
callback_(std::forward<Args>(args)...);
return;
}
std::cout << "uh-oh, callback is dead!" << std::endl;
}
template<class... Args>
auto operator()(Args&&... args) -> typename std::enable_if<!std::is_void<typename std::result_of<Func(Args...)>::type>::value,
boost::optional<typename std::result_of<Func(Args...)>::type>>::type
{
std::cout << "trying non-void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
return callback_(std::forward<Args>(args)...);
}
std::cout << "uh-oh, callback is dead!" << std::endl;
return boost::none;
}
bool isAlive()
{
return guard_.lock();
}
private:
std::weak_ptr<bool> guard_;
Func callback_;
};
class SafeCallbackProvider
{
public:
SafeCallbackProvider()
: guard_(new bool(true))
{}
virtual ~SafeCallbackProvider() = default;
template<class Func>
SafeCallback<Func> makeSafeCallback(const Func& callback)
{
return SafeCallback<Func>(guard_, callback);
}
private:
std::shared_ptr<bool> guard_;
};
struct A : SafeCallbackProvider
{
void fun()
{
std::cout << "---this is fun---" << std::endl;
}
int fun(int&& i)
{
std::cout << "&& this is && " << i << " && fun &&" << std::endl;
return i;
}
// int fun(int i) // fails to compile with: 123:48: error: call of overloaded 'fun(int)' is ambiguous
int fun(int& i)
{
std::cout << "---this is ---" << i << "--- fun---" << std::endl;
return i;
}
};
int main()
{
A* a= new A;
auto cb = a->makeSafeCallback(
[&]()
{
a->fun();
});
cb();
delete a;
cb();
std::cout << "\n----------\n\n";
A* a2= new A;
auto cb2 = a2->makeSafeCallback(
[&](int i)
{
return a2->fun(i);
});
cb2(5);
delete a2;
cb2(5);
std::cout << "\n----------\n\n";
A* a3= new A;
auto cb3 = a3->makeSafeCallback(
[&](int&& i)
{
return a3->fun(std::forward<int>(i));
});
cb3(5);
delete a3;
cb3(5);
return 0;
}
Note: this only answers the first question, because I apparently have the attention span of a fly. More coming soon.
std::result_of essentially performs some magic based on a function type that looks like a function call. In the line that works:
typename std::result_of<Func(Args...)>::type
This is the intended use, simulating the call of an instance of Func with values of types Args.... On the other hand:
typename std::result_of<Func(std::forward<Args>(args)...)>::type
This expands Args and args into a group of values, which then form a chain of ,-operators inside a functoin-style cast to Func. The whole thing is an expression instead of the type std::result_of expects.
It looks like you're halfway to using decltype instead, which would look like:
decltype(std::declval<Func&>()(std::forward<Args>(args)...))
... or, if you can be bothered to move it underneath callback_'s declaration:
decltype(callback_(std::forward<Args>(args)...))
Rules of Overloading are that .
Signature of function should be different.
In both the case compiler is finding same signature, try to change the signature and see the result.
Recently I tried to reinvent scope guard via std::unique_ptr (NOTE: Deleter has the member typedef pointer — is a specially handled case of std::unique_ptr):
#include <type_traits>
#include <utility>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <cassert>
namespace
{
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
using pointer = std::decay_t< lambda >;
void
operator () (lambda & l) const noexcept
{
std::forward< lambda >(l)();
}
};
return std::unique_ptr< std::decay_t< lambda >, lambda_caller >(std::forward< lambda >(_lambda));
}
}
int
main()
{
std::cout << 1 << std::endl;
{
std::cout << 2 << std::endl;
[[gnu::unused]] auto && guard_ = make_scope_guard([&] { std::cout << __PRETTY_FUNCTION__ << std::endl; });
std::cout << 3 << std::endl;
}
std::cout << 5 << std::endl;
return EXIT_SUCCESS;
}
Such an approach works fine for simple pointer to free function void f() { std::cout << 4 << std::endl; } passed to make_scope_guard, but not for any lambda passed to make_scope_guard.
This is due to an abundance of ... = pointer() into the std::unique_ptr definition (function default parameter, defaulting data memebers etc), but I can't find the DefaultConstructible requirement for pointer into this article.
Is it mandatory, that the pointer should match the std::is_default_constructible requirement?
It tested against libc++ and against libstdc++ using not too old clang++ -std=gnu++1z.
Seems, there should be language extension for lambdas: if auto l = [/* possible capture list */] (Args...) { /* code */; }; then using L = decltype(l); is equivalent to struct L { constexpr void operator () (Args...) const noexcept { ; } }; for some Args..., isn't it?
ADDITIONAL:
Providing the instance D{} of following DefaultConstructible class to make_scope_guard(D{}) requires commented out code to be uncommented in the context if (p) { ..., where p is of type D:
struct D { void operator () () const noexcept { std::cout << __PRETTY_FUNCTION__ << std::endl; } /* constexpr operator bool () const { return true; } */ };
A unique_ptr is still a pointer. You cannot shoehorn a lambda into it. From [unique.ptr]:
A unique pointer is an object that owns another object and manages that other object through a pointer.
More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of
p when u is itself destroyed
[...]
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following post-conditions hold: [...] u.p is equal to nullptr
A lambda is not a pointer. A lambda cannot equal nullptr.
That said, you're already making your own local struct, why not just use that to do the RAII scope guarding itself instead of deferring to unique_ptr? That seems like a hack at best, and takes more code to boot. You could instead just do:
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
lambda _lambda;
~lambda_caller()
{
_lambda();
}
};
return lambda_caller{std::forward<lambda>(_lambda)};
}
If you need to support release, you can wrap _lambda inside of boost::optional so that lambda_caller becomes:
struct lambda_caller
{
boost::optional<lambda> _lambda;
~lambda_caller()
{
if (_lambda) {
(*_lambda)();
_lambda = boost::none;
}
}
void release() {
_lambda = boost::none;
}
};
Here is the code. It does not compile in vs2013, but does compile in gcc4.8
error C2665: 'std::thread::thread' : none of the 4 overloads could convert all the argument types
Since I am using vs2013, can anyone provide workaround?
#include <iostream>
#include <thread>
template<typename T>
class TestClass
{
public:
TestClass(){};
~TestClass(){};
T t;
template<typename U>
void fun(U u)
{
std::cout << "fun: " << u << '\n';
}
};
int main()
{
TestClass<double> A;
auto aaa = std::thread(&TestClass<double>::fun<int>, &A, 1);
}
You could simply use a lambda rather than monkeying with member function pointers:
auto aaa = thread( [&]{ A.fun(1); } );
aaa.join();
There is another way you can achieve above problem,If you would mind !
First just look explicit constructor of thread object:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
f - Universal reference for function object.
args - variadic arguments for function(functor) f.
(I am not going to explain deeper and deeper about variadic calling used here).
So now we know we can deal with functors therefore,
Define a functor(function object) like below :
template<typename T>
class TestClass
{
public:
TestClass(){};
~TestClass(){};
T t;
template<typename U>
void operator()(U u1,U u2){
std::cout << "fun: " << u1*u2 << '\n';
}
};
int main()
{
TestClass<double> A;
auto aaa = std::thread(A,1,100);// calling functor A(1,100)
aaa.join()
//or if you can move object from main thread to manually created thread aaa ,it's more elegant.
auto aa = std::thread(std::move(A),1,100);
aa.join();
A(1, 99);
system("Pause");
return 0;
}
//Please notice here I've not used any locker guard system.
If you use static function you don't have to bind respective instance each time this may change your expected run-time behavior therefore you have to managed,
template<typename U>
static void fun(U u)
{
std::cout << "fun: " << u << '\n';
}
then invoke the function,
int main()
{
TestClass<double> A;
auto aaa = std::thread(&TestClass<double>::fun<int>, 1);
system("Pause");
return 0;
}