I would kindly ask someone to explain me a bit why an enum can only be passed by right reference and not as simple reference ?
namespace n1
{
enum e1
{
f = 1,
f1
};
}
void f(n1::e1&& e)
{
std::cout<<static_cast<int>(e);
}
int main()
{
f(n1::e1::f1);
return 0;
}
enums are constants so you can't take it as n1::e1& but as const n1::e1&:
void f(const n1::e1& e) {
std::cout<<static_cast<int>(e);
}
Enumerations are integral constants :
an enum parameter of a function must be constant
Remark : you don't have to cast the enum to print his value
void f(const n1::e1& e) {
std::cout<< e ;
}
Related
For example, if I have a bool value v, I want a reference to !v that can change when v changes. An example use will be:
class A {
bool& isOpen;
A(bool& value): isOpen(value) {}
void f() {
if (isOpen) {
doSomething();
}
}
};
class B {
bool& isClosed;
B(bool& value): isClosed(value) {}
void g() {
if (isClosed) {
doSomething();
}
}
};
int main() {
bool isOpen = true;
A a(isOpen);
B b(negattive_reference_of(isOpen));
a.f(); // doSomething()
b.g(); // do nothing
isOpen = false;
a.f(); // do nothing
b.g(); // doSomething()
}
Is there anyway in C++ to acheive a similar effect?
Under the hood reference is equivalent to a constant pointer to some variable (compiler just gives you a syntax sugar of how to work with such pointers so that they are always initialized).
So you wan't to have the same variable and two different pointers to it, one of which will dereference to true and the other to false. That is obviously impossible.
The OOP -way to do it would be to pass not reference to boolean but some interface to your classes and use implementation that uses same boolean variable:
class IIsOpenProvider
{
public:
virtual ~IIsOpenProvider() = 0;
virtual bool GetOpenValue() = 0;
};
class IIsClosedProvider
{
public:
virtual ~IIsClosedProvider() = 0;
virtual bool GetClosedValue() = 0;
};
class ValueProvider : public IIsOpenProvider, public IIsClosedProvider
{
public:
bool GetOpenValue() override { return isOpen; }
bool GetClosedValue() override { return !isOpen; }
private:
bool isOpen;
};
class A {
IIsOpenProvider& isOpen;
A(IIsOpenProvider& value): isOpen(value) {}
void f() {
if (isOpen.GetOpenValue()) {
doSomething();
}
}
};
class B {
IIsClosedProvider& isClosed;
B(IIsClosedProvider& value): isClosed(value) {}
void g() {
if (IIsClosedProvider.GetClosedValue()) {
doSomething();
}
}
};
// usage
ValueProvider val;
A a(val);
B b(val);
Just like passing class type as argument to method I want to pass enum, as I want to write a general method which operates on enum.
I tried:
void foo(E):
print(E.values[0])
but it doesn't work.
Is there a way?
This might work for you
typedef EnumValues<T> = List<T> Function();
void main() {
foo<E1>(() => E1.values);
foo<E2>(() => E2.values);
}
enum E1 { a, b }
enum E2 { c, d }
void foo<T>(EnumValues<T> valuesFn) {
var values = valuesFn();
for (var v in values) {
print(v);
}
}
See comments - shorter version
void main() {
foo<E1>(E1.values);
foo<E2>(E2.values);
}
enum E1 { a, b }
enum E2 { c, d }
void foo<T>(List<T> values) {
for (var v in values) {
print(v);
}
print(values[0]);
}
How to pass lambda as template parameter.
For example this code
template<void (*callback)()>
void function() {
callback();
}
int main() {
function<[]() -> void { std::cout << "Hello world\n"; }>();
}
fails with error "invalid template argument for 'function', expected compile-time constant expression".
What I'm doing wrong.
Edit
I want to implement something like this
template<typename T,
T (*deserializer)(buffer *data),
void (*serializer)(T item, buffer *data)>
class Type {
public:
T item;
Type(T item) : item(item) {
}
Type(buffer *data) {
deserialize(data);
}
void serialize(buffer *data) {
serializer(item, data);
}
void deserialize(buffer *data) {
deserializer(data);
}
};
typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType
typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType
Lambdas in C++14, including their conversion to function pointers, are not constexpr.
In C++17, this is going to change. There are no stable compilers with that feature implemented that I'm aware of (if you find one, can you mention it in the comments below?).
At that point
constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; };
function<+tmp>();
will definitely work. I am uncertain if
function<+[]() -> void { std::cout << "Hello world\n"; }>()
would work; there are some rules about lambdas in unevaluated contexts and inside template argument lists that may be separate from the constexpr lambda problem and may apply here.
We can hack it in C++14.
Create a template class that stores a static copy of a lambda and exposes a static function with the same signature (f_ptr) that calls that static copy of a lambda.
Instantiate it once globally with your lambda.
Pass a pointer to the f_ptr to your template.
So:
template<class L> struct stateless; // todo
template<class L> stateless<L> make_stateless(L l){return std::move(l);}
auto foo = make_stateless( []() -> void { std::cout << "Hello world\n"; } );
function< &foo::f_ptr >();
this is almost certainly not what you want.
The kind of template in the example does not take a type as a parameter, but rather a value. This value needs to be determinable at runtime, in order to instantiate the template, and the value of a lambda is not a compile time constant, so this method just wont do. The common way of sending functors to a function is:
template<typename Func>
void foo(Func&& f)
{
f();
}
And since you want a class template (please put such information in the question, not the comments), here is an example using classes:
#include <utility>
template<typename Func>
class MyClass
{
public:
MyClass(Func&& f) : f(f) {}
void Run() { f(); }
private:
Func f;
};
template<typename Func>
MyClass<Func> MakeMyClass(Func&& f)
{
return { std::forward<Func>(f) };
}
int main()
{
auto x = MakeMyClass( [](){} );
x.Run();
}
In g++ I could do this:
struct s
{
int a, b;
};
void MyFunction(s) { }
int main()
{
MyFunction((s) { 0, 0 });
return 0;
}
In Visual Studio however, it doesn't work. is there any way to make it work or some alternative syntax without making a variable and initializing it (and without adding a constructor to the struct as it will make it non-aggregate and it wouldn't be able to initialize in aggregates)?
My C is a bit rusty, but didn't you have to use struct s unless you typedef it? Something like this:
struct s
{
int a, b;
};
void MyFunction(struct s) { }
int main()
{
MyFunction((struct s) { 0, 0 });
return 0;
}
or
typedef struct s
{
int a, b;
} s_t;
void MyFunction(s_t) { }
int main()
{
MyFunction((s_t) { 0, 0 });
return 0;
}
I have this function:
void func(boost::function<void(float)> cb){
//do something with cb()
}
It works with lambdas and functions.
But it does not allow me to pass a member function or a lambda defined in a member function.
I tried to cast something like this:
void class::memberFunc() {
void func((void(*)(float))([](float m){}));
}
But it seems like lambda is ignored at calls.
And no idea how to pass a member function too.
Given:
struct T {
T(int x) : x(x) {};
void foo() {
std::cout << x;
}
int x;
};
The object pointer is an implicit first parameter to functions, and this becomes explicit when dealing with boost::function.
You can "hide" it from func by binding it early:
void func(boost::function<void()> cb) {
cb();
}
int main() {
T t(42);
func(boost::bind(&T::foo, &t));
}
Or otherwise you can bind it late:
T t(42);
void func(boost::function<void(T*)> cb) {
cb(&t);
}
int main() {
func(boost::bind(&T::foo, _1));
}
See it working here.