template<typename T>
class Pack
{
private:
std::function<T()> _Func = nullptr;
public:
Pack()
{
}
Pack(std::function<T()> func)
: _Func(func)
{
}
~Pack()
{
}
operator T()
{
return _Func();
}
};
What I use is operator T, I want to call _Func implicitly but I cannot even do it explicitly. It seems right but actually error C2440 #MSVC. I use it in two ways:
static member of class (succeeded);
member of class (failed)
(I don't know whether it matters or not)
I'm really wondering why it performs in two ways, and more importantly, how I can put it into my class as a non-static member and successfully call the operator T.
Member of the class:
struct test
{
test()
{
p_ = Pack<int>(std::bind(&test::foo, *this));
}
int foo()
{
std::cout << "test::foo" << std::endl;
return 5;
}
Pack<int> p_;
};
int main()
{
test t;
int x = t.p_;
return 0;
}
This works fine on VS 2013 EE.
Related
I have a class like this one:
struct Base
{
void aa(int n) const {
std::cout << "aa() " << field*n << std::endl;
}
void bb(int n) const {
std::cout << "bb() " << field*n*2 << std::endl;
}
int field = 2;
};
I want to be able to select, at compile time, one of the two implementations, aa() or bb(), via a call to an operator method. Something like:
Base data;
Magic obj(data);
obj.as_AA() * 33; // should call data.aa(33)
obj.as_BB() * 44; // should call data.bb(44)
data must not be duplicated. And the choice of aa() vs bb() must be resolved at compile time.
I have a solution which uses a downcasting whose behavior is in theory undefined (I think). It builds (with g++ and clang++) and runs perfectly, but still ...
struct AA : public Base
{
void operator*(int n) const {
return Base::aa(n);
}
};
struct BB : public Base
{
void operator*(int n) const {
return Base::bb(n);
}
};
struct Chooser
{
Base obj;
template<typename WHICH> // will be either AA or BB
const WHICH& as() const {
return static_cast<const WHICH&>( obj ); // downcasting
}
};
In main.cpp:
Chooser ch;
ch.as<AA>() * 5; // prints "aa() 10"
ch.as<BB>() * 7; // prints "bb() 28"
How unreliable is my solution? (because of the downcasting which is technically undefined)
Do you see alternatives?
Thanks
ps: of course I could trivially use
Base data;
data.aa(33);
data.bb(44);
but I really want to access the different implementations via the same name, ie., the operator*
I could also use a templated operator* in Base and have explicit template specializations, however that would force me to use an ugly syntax, which kind of voids the purpose of the operator:
struct Base {
\\...
template<int N> void operator*(int n) const;
};
template<> void Base::operator*<1>(int n) const {
aa(n);
}
Which requires:
Base data;
data.operator*<1>(44); // ugly
You could write the Magic class like this:
struct Magic {
Magic(Base &b) : b(b) {}
Base &b;
struct AA {
Base &b;
void operator*(int n) const {
return b.aa(n);
}
};
struct BB {
Base &b;
void operator*(int n) const {
return b.bb(n);
}
};
AA as_AA() { return AA{b}; }
BB as_BB() { return BB{b}; }
};
This avoids any inheritance by using composition instead. Also, there is no copy of the data object, since only references are being made to it.
Now you can use exactly the calling syntax that you want, and it has the right behavior:
Base data;
Magic obj(data);
obj.as_AA() * 33; // calls data.aa(33) -- prints 66
obj.as_BB() * 44; // calls data.bb(44) -- prints 176
Here's a demo.
One solution for using the same function name is to strongly type the argument:
struct AA {
int n;
};
struct BB {
int n;
};
void call(Base& base, AA arg) {
base.aa(arg.n);
}
void call(Base& base, BB arg) {
base.bb(arg.n);
}
...
Base data;
call(data, AA{33});
call(data, BB{44});
I took the liberty of getting rid of the operator overloading since this still accesses different implementations using the same name.
If you're trying to go further by having the same calling code with the selection being done in advance, you can use a higher-order function:
auto call_aa(Base& base) {
return [&](int n) { return base.aa(n); };
}
auto call_bb(Base& base) {
return [&](int n) { return base.bb(n); };
}
...
Base data;
auto aa = call_aa(data);
aa(33);
call_bb(data)(44);
Consider this pseudo-snippet:
class SomeClass
{
public:
SomeClass()
{
if(true)
{
fooCall = [](auto a){ cout << a.sayHello(); };
}
else
{
fooCall = [](auto b){ cout << b.sayHello(); };
}
}
private:
template<typename T>
std::function<void(T)> fooCall;
};
What I want is a class member fooCall which stores a generic lambda, which in turn is assigned in the constructor.
The compiler complains that fooCall cannot be a templated data member.
Is there any simple solution on how i can store generic lambdas in a class?
There is no way you'll be able to choose between two generic lambdas at run-time, as you don't have a concrete signature to type-erase.
If you can make the decision at compile-time, you can templatize the class itself:
template <typename F>
class SomeClass
{
private:
F fooCall;
public:
SomeClass(F&& f) : fooCall{std::move(f)} { }
};
You can then create an helper function to deduce F:
auto makeSomeClassImpl(std::true_type)
{
auto l = [](auto a){ cout << a.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}
auto makeSomeClassImpl(std::false_type)
{
auto l = [](auto b){ cout << b.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}
template <bool B>
auto makeSomeClass()
{
return makeSomeClassImpl(std::bool_constant<B>{});
}
I was not able to store std::function<> as a generic lambda in the class directly as a member. What I was able to do was to specifically use one within the class's constructor. I'm not 100% sure if this is what the OP was trying to achieve but this is what I was able to compile, build & run with what I'm suspecting the OP was aiming for by the code they provided.
template<class>
class test {
public: // While testing I changed this to public access...
// Could not get object below to compile, build & run
/*template<class U = T>
static std::function<void(U)> fooCall;*/
public:
test();
};
template<class T>
test<T>::test() {
// This would not compile, build & run
// fooCall<T> = []( T t ) { std::cout << t.sayHello(); };
// Removed the variable within the class as a member and moved it here
// to local scope of the class's constructor
std::function<void(T)> fooCall = []( auto a ) { std::cout << a.sayHello(); };
T t; // created an instance of <Type T>
fooCall(t); // passed t into fooCall's constructor to invoke the call.
}
struct A {
std::string sayHello() { return "A say's Hello!\n"; }
};
struct B {
std::string sayHello() { return "B say's Hello!\n"; }
};
int main() {
// could not instantiate an object of SomeClass<T> with a member of
// a std::function<> type that is stored by a type of a generic lambda.
/*SomeClass<A> someA;
SomeClass<B> someB;
someA.foo();
someB.foo();*/
// Simply just used the object's constructors to invoke the locally stored lambda within the class's constructor.
test<A> a;
test<B> b;
std::cout << "\nPress any key & enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
With the appropriate headers the above as is should compile, build & run giving the output below (At least in MSVS 2017 on Windows 7 64bit did); I left comments where I ran into errors and tried multiple different techniques to achieve a working example, errors occurred as others suggested and I found even more while working with the above code. What I was able to compile, build and run came down to this simple bit of code here without the comments. I also added another simple class to show it will work with any type:
template<class>
class test {
public:
test();
};
template<class T>
test<T>::test() {
std::function<void( T )> fooCall = []( auto a ) { std::cout << a.sayHello(); };
T t;
fooCall( t );
}
struct A {
std::string sayHello() { return "A say's Hello!\n"; }
};
struct B {
std::string sayHello() { return "B say's Hello!\n"; }
};
struct C {
int sayHello() { return 100; }
};
int main() {
test<A> testA;
test<B> testB;
test<C> testC;
std::cout << "\nPress any key & enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
Output:
A say's Hello!
B say's Hello!
100
Press any key & enter to quit
I don't know if this will help the OP directly or indirectly or not but if it does or even if it doesn't it is still something that they may come back to and build off of.
you can simply use a template class or...
If you can get away with using c++17, you could make fooCall's type std::function<void(const std::any&)> and make a small wrapper for executing it.
method 1 : simply use a template class (C++14).
method 2 : seems to mimic the pseudo code exactly as the OP intended (C++17).
method 3 : is a bit simpler and easier to use than method 2 (C++17).
method 4 : allows us to change the value of fooCall (C++17).
required headers and test structures for the demo :
#include <any> //not required for method 1
#include <string>
#include <utility>
#include <iostream>
#include <functional>
struct typeA {
constexpr const char * sayHello() const { return "Hello from A\n"; }
};
struct typeB {
const std::string sayHello() const { return std::string(std::move("Hello from B\n")); }
};
method 1 :
template <typename T>
class C {
const std::function<void(const T&)> fooCall;
public:
C(): fooCall(std::move([](const T &a) { std::cout << a.sayHello(); })){}
void execFooCall(const T &arg) {
fooCall(arg);
}
};
int main (void) {
typeA A;
typeB B;
C<typeA> c1;
C<typeB> c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 2 :
bool is_true = true;
class C {
std::function<void(const std::any&)> fooCall;
public:
C() {
if (is_true)
fooCall = [](const std::any &a) { std::cout << std::any_cast<typeA>(a).sayHello(); };
else
fooCall = [](const std::any &a) { std::cout << std::any_cast<typeB>(a).sayHello(); };
}
template <typename T>
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C c1;
is_true = false;
C c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 3 :
/*Note that this very closely resembles method 1. However, we're going to
build off of this method for method 4 using std::any*/
template <typename T>
class C {
const std::function<void(const std::any&)> fooCall;
public:
C() : fooCall(std::move([](const std::any &a) { std::cout << std::any_cast<T>(a).sayHello(); })) {}
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C<typeA> c1;
C<typeB> c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 4 :
/*by setting fooCall outside of the constructor we can make C a regular class
instead of a templated one, this also complies with the rule of zero.
Now, we can change the value of fooCall whenever we want.
This will also allow us to do things like create a container that stores
a vector or map of functions that each take different parameter types*/
class C {
std::function<void(const std::any&)> fooCall; //could easily be replaced by a vector or map
public:
/*could easily adapt this to take a function as a parameter so we can change
the entire body of the function*/
template<typename T>
void setFooCall() {
fooCall = [](const std::any &a) { std::cout << std::any_cast<T>(a).sayHello(); };
}
template <typename T>
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C c;
c.setFooCall<typeA>;
c.execFooCall(A);
c.setFooCall<typeB>;
c.execFooCall(B);
return 0;
}
Output from Any method
Hello from A
Hello from B
I have a question about equality comparison of lambdas.
I've tried to read some references but I've found nothing about this.
[] (Args ...args) -> ReturnType { ... };
For this type of lambdas, which are not closures actually because they have empty capture list, operators == and != works in the same way as for static functions (well, it seems, compiler generates them as static functions as well). But for closures any attempt to compare in the same way causes compilation error.
Here is simple programm for example:
#include <typeinfo>
#include <iostream>
struct WrapperBase {
virtual ~WrapperBase() = default;
virtual bool operator==(WrapperBase& v) = 0;
virtual bool operator!=(WrapperBase& v) = 0;
};
template<typename _Tp>
struct Wrapper : WrapperBase {
Wrapper(const _Tp& v) : value(v) { }
bool operator==(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value == vv.value;
}
catch(std::bad_cast& err) { }
return false;
}
bool operator!=(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value != vv.value;
}
catch(std::bad_cast& err) { }
return true;
}
//
_Tp value;
};
template<typename _Tp>
WrapperBase* create_wrapper(const _Tp& v) {
return new Wrapper<_Tp>(v);
}
struct Base {
Base(int a, int b) : wrapper(nullptr), a(a), b(b) { }
virtual ~Base() { delete wrapper; }
virtual WrapperBase* create_wrapper() = 0;
WrapperBase* wrapper;
int a;
int b;
};
struct ClassA : Base {
ClassA(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [] (int v1, int v2) { return v1 + v2; };
return ::create_wrapper(lambda);
}
};
struct ClassB : Base {
ClassB(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [=] (int v1, int v2) { return a + b + v1 + v2; };
return ::create_wrapper(lambda);
}
};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
// all works fine:
ClassA a1(1, 2);
ClassA a2(3, 4);
std::cout << (*a1.wrapper == *a1.wrapper) << std::endl; // true
std::cout << (*a2.wrapper == *a2.wrapper) << std::endl; // true
std::cout << (*a1.wrapper == *a2.wrapper) << std::endl; // true
// cause compilation error:
ClassB b1(1, 2);
ClassB b2(3, 4);
std::cout << (*b1.wrapper == *b1.wrapper) << std::endl;
std::cout << (*b2.wrapper == *b2.wrapper) << std::endl;
std::cout << (*b1.wrapper == *b2.wrapper) << std::endl;
return 0;
}
Comparing lambdas created in instances of ClassA always return true even if they are created in different context (just as I said). On the other hand, ClassB do not even compile because operator == and != for its lambda is not found.
It seems, this programm is not well-formed, and comparing of lambdas in the way I've tried causes undefined behavior of the programm. But if it's really undefined behavior, how can they be compared? (I guess, nohow)
For this type of lambdas, which are not closures actually because they
have empty capture list, operators == and != works in the same way as
for static functions (well, it seems, compiler generates them as
static functions as well).
It works because the closure type of a lambda without captures provides a conversion operator that returns a function pointer. Those are comparable. [expr.prim.lambda]/6 (emphasis mine):
The closure type for a lambda-expression with no lambda-capture
has a public non-virtual non-explicit const conversion function to
pointer to function having the same parameter and return types as the
closure type’s function call operator. The value returned by this
conversion function shall be the address of a function that, when
invoked, has the same effect as invoking the closure type’s function
call operator.
(If the conversion operator was explicit the comparison would not work)
Roughly, a lambda of the form [] {} translates to
struct closure_type
{
private:
static void call() {}
public:
// closure_type() = delete; // Commented for the sake of the demo
closure_type& operator=(closure_type const&) = delete;
void operator()() const { /*return call();*/ }
operator decltype(&call)() const
{
return &call;
}
};
As you may have noted, the conversion operator returns the same function pointer each time. Though it would be utterly surprising if anything the like happened, the standard does allow different function pointers to be returned for a call to the conversion operator for the same closure object; A comparison of two closure objects has therefore an implementation-defined value. (It should, though, on all implementations be true for two closure objects of the same type.)
I have the following code:
#include <iostream>
struct Base {
int i_;
};
class El : protected Base {
public:
int get_i() const { return i_; }
void set_i(int i) { i_ = i; }
};
class It : protected Base {
public:
using pointer = const El*;
using reference = const El&;
reference operator*() const
{
return reinterpret_cast<reference>(*this);
}
pointer operator->() const
{
return reinterpret_cast<pointer>(this);
}
};
int main()
{
It it;
It* itp = ⁢
std::cout << *****(itp)->get_i() << "\n"; //ERROR
}
Both GCC and Clang++ somehow fail to invoke either of operator* or operator->, so I get an error It doesn't have member function 'get_i' in the last line regardless how many indirections I try. Does the standard warrant such unintuitive behavior?
Operator precedence: -> binds more tightly, so is applied to the pointer itp.
When you overload operator->, that doesn't affect the meaning of operator-> applied to a pointer-to-your-class. You want (*itp)->get_i();, I think.
I tried to build a minimal example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}
My question about this: Why is it even possible to call the operator on the pure type without an object? How can I call the function other the same way as I call operator()?
You're not calling it on a pure type. foo() invokes the constructor, and evaluates to a temporary foo object, on which you then invoke operator().
To do the equivalent with a "normal" member function, just do:
foo().other(a);
You are not "call[ing] the operator on the pure type without an object". The syntax foo()(a) is creating a temporary of type foo (this is the foo() part) and then calling operator() on that object with a as argument: (the (a) part).
Pure type example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
static void one_more(int& a)
{
a += 3;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
foo().other(a);
foo::one_more(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}