Rust generics: list where each element is from the same trait? - templates

I found this question on the Rust users forum : Generics: Can I say "tuple where each element is FromSql". Basically, the questions was to know how do something like that :
trait Foo {}
struct A {}
impl Foo for A {}
struct B {}
impl Foo for B {}
fn main() {
let x = (A{}, A{}, B{}, A{});
bar(x);
}
fn bar<T: Foo>(tuple: (T...)) {
}
This code does not work, it's an idea of how it could look like.
So, how can we do that?

The first step is to create a ToAny trait that will be implemented for all our structures.
use std::any::Any;
pub trait ToAny {
fn as_any(&self) -> &dyn Any;
}
Let's create our trait
trait Foo: ToAny {}
It requires implementing the ToAny trait to force each structure implementing Foo to implement ToAny too.
Let's create our structures:
struct A {
id: i32,
}
impl ToAny for A {
fn as_any(&self) -> &dyn Any {
self
}
}
impl Foo for A {}
struct B {
id: i32,
}
impl ToAny for B {
fn as_any(&self) -> &dyn Any {
self
}
}
impl Foo for B {}
The implementation of ToAny is always the same, we could create a macro implementing it easily.
And then, we can create a Vec instead of a tuple to store our values:
let boxeds: Vec<Box<dyn A>> = vec![
Box::new(A {id: 1}),
Box::new(B {id: 2}),
Box::new(A {id: 3}),
Box::new(B {id: 4}),
];
// Stores the values being `B`.
let mut bees: Vec<&B> = vec![];
for boxed in &boxeds {
// `Some(x)` if `boxed` contains a `B` value.
let found = match boxed.as_any().downcast_ref::<B>() {
Some(b) => b,
None => {}, // it is a `A` value.
};
bees.push(found);
}
assert_eq!(bees, vec![
&B {id: 2},
&B {id: 4}
]);
If we refer to the question, the following code:
fn bar<T: Foo>(tuple: (T...)) {
}
can be this valid code:
fn bar(values: Vec<Box<dyn Foo>>) {
}
I've written a gist file being tests for that. Be careful, I've changed the names in this post, Foo is A and there is only the B structure.

Use a macro to implement Foo for tuples:
trait Foo {
fn do_it(&self);
}
struct A {}
impl Foo for A {
fn do_it(&self) {
print!("A");
}
}
struct B {}
impl Foo for B {
fn do_it(&self) {
print!("B");
}
}
fn main() {
let x = (A{}, A{}, B{}, A{});
bar(x);
}
fn bar<T: Foo>(tuple: T) {
tuple.do_it();
}
macro_rules! impl_Foo_for_tuple {
( $first:ident $($rest:ident)* ) => {
impl< $first: Foo, $( $rest : Foo, )* > Foo for ( $first, $($rest,)* ) {
fn do_it(&self) {
#[allow(non_snake_case)]
let ( $first, $($rest,)* ) = self;
$first.do_it();
$( $rest.do_it(); )*
}
}
impl_Foo_for_tuple!( $($rest)* );
};
() => {};
}
impl_Foo_for_tuple!(A B C D E F G H I J K L M);

Related

how do you implement an EventDispatcher the rust way?

So I have been trying to create a rendering engine using rust, and I've been basing it on some C++ code that does the same thing. And I'm stuck on how you write an event dispatcher the rusty way.
here's the C++ code
class EventDispatcher {
template<typename T>
using EventFn = std::function<bool(T&)>;
public:
EventDispatcher(Event& event) : m_Event(event) {}
template<typename T>
bool Dispatch(EventFn<T> func) {
if (m_Event.GetEventType() == T::GetStaticType()) {
m_Event.m_Handeled = func(*(T*)&m_Event);
return true;
}
return false;
}
private:
Event& m_Event;
};
and it will be used like this
void SomeOtherClass::OnEvent(Event& e) {
EventDispatcher dispatcher(e);
dispatcher.Dispatch<RandomEvent>(std::bind(&Application::EventHandler, this, std::placeholders::_1));
}
I've tried to implement a similar pattern in rust, this is what I've got so far
pub struct EventDispatcher<T: EventTrait> {
event: Box<T>,
}
impl<T: EventTrait> EventDispatcher<T> {
pub fn dispatch<V: EventTrait>(&mut self, func: impl Fn(&mut V) -> bool) -> bool {
if self.event.type_id() == TypeId::of::<V>() {
let res = func(unsafe { &mut *(self.event as *mut T as *mut V) });
self.event.set_is_handeled(res);
return res;
} else {
false
}
}
}
I'm pretty sure this is horribly wrong, I'm still trying to learn rust. Any help would be greatly appreciated! :D
well I figured that my current approach wasn't the best, I tried to implement the observer pattern for this problem, and I feel that it's a better fit!
pub trait IObserver {
fn update(&self, event: &impl EventTrait);
}
pub trait ISubject<'a, T: IObserver> {
fn attach(&mut self, observer: &'a T);
fn detach(&mut self, observer: &'a T);
fn notify(&self, event: &impl EventTrait);
}

How to access operator[] from inside of a derived class in C++? [duplicate]

The following works but feels ugly when I do the (*this)(5) part.
struct MyStruct
{
void operator()(int a)
{
// Do something with "a"
}
void myFunc()
{
(*this)(5);
}
};
I will need to overload the () operator and use it from within other class methods.
You have a few options:
(*this)(5)
this->operator()(5)
or just operator()(5)
Create a method that you call from within the operator(), e.g.:
void do_work(int a) { /* ... */ }
void operator()(int a) { do_work(a); }
void myFunc() { do_work(5); }
Whichever you choose is just a matter of personal taste.
Just for fun, here are some more (ridiculous) options:
std::invoke (mentioned in comments):
std::invoke(&MyStruct::operator(), this, 5);
mem_fn:
auto call_op = std::mem_fn(&MyStruct::operator());
call_op(this, 5);
lambda:
auto call_op = [this] (int a) { operator()(a); };
call_op(5);
bind_front
auto call_op = std::bind_front(&MyStruct::operator(), this);
call_op(5);

How can I invoke an overloaded () operator on the keyword this?

The following works but feels ugly when I do the (*this)(5) part.
struct MyStruct
{
void operator()(int a)
{
// Do something with "a"
}
void myFunc()
{
(*this)(5);
}
};
I will need to overload the () operator and use it from within other class methods.
You have a few options:
(*this)(5)
this->operator()(5)
or just operator()(5)
Create a method that you call from within the operator(), e.g.:
void do_work(int a) { /* ... */ }
void operator()(int a) { do_work(a); }
void myFunc() { do_work(5); }
Whichever you choose is just a matter of personal taste.
Just for fun, here are some more (ridiculous) options:
std::invoke (mentioned in comments):
std::invoke(&MyStruct::operator(), this, 5);
mem_fn:
auto call_op = std::mem_fn(&MyStruct::operator());
call_op(this, 5);
lambda:
auto call_op = [this] (int a) { operator()(a); };
call_op(5);
bind_front
auto call_op = std::bind_front(&MyStruct::operator(), this);
call_op(5);

Check if class member is static

I have code like this and I want to check in my template (using a static if), if C.foo and C.bar are static or not:
class C {
int foo;
static int bar;
}
I tried these traits already but they don't seem to change for static members:
pragma(msg, __traits(hasMember, C, "foo")); // -> true
pragma(msg, __traits(hasMember, C.init, "foo")); // -> true
pragma(msg, __traits(hasMember, C, "bar")); // -> true
pragma(msg, __traits(hasMember, C.init, "bar")); // -> true
This hack which actually works for structs doesn't work for classes either:
pragma(msg, __traits(compiles, { enum tmp = __traits(getMember, C, "foo"); })); // -> false
pragma(msg, __traits(compiles, { enum tmp = __traits(getMember, C.init, "foo"); })); // -> false
pragma(msg, __traits(compiles, { enum tmp = __traits(getMember, C, "bar"); })); // -> false
pragma(msg, __traits(compiles, { enum tmp = __traits(getMember, C.init, "bar"); })); // -> false
The trick is that static member variables do not have an offsetof property. So, you can do something like
template isStaticMember(T, string memberName)
if(__traits(hasMember, T, memberName))
{
mixin("alias member = " ~ T.stringof ~ "." ~ memberName ~ ";");
enum isStaticMember = !__traits(compiles, member.offsetof);
}
class C
{
int foo;
static int bar;
}
void main()
{
static assert(!isStaticMember!(C, "foo"));
static assert(isStaticMember!(C, "bar"));
}
There probably should be something in std.traits for this, but there isn't yet.

Is there a C++ new declaration like in C#

I wondered if there was a new declaration like in C# for C++
C# allows you to do this and it just neatens up the code a bit:
FuncCall( new Foo() {
Bar = "sausage",
Boo = 4
} );
It's just I thought this was a bit sloppy in C++:
unique_ptr<Foo> foo( new Foo() );
foo.Bar = "sausage";
foo.Boo = 4;
FuncCall( move( foo ) );
Foo might look like this:
class Foo
{
public:
Foo();
string Bar;
int Boo;
}
Why am i not just placing all into construct paramters?
Because it's stupid when you have to initalize so much:
Foo( int width, int height, string title, string className, string thjis, stihjrjoifger gfirejgoirejgioerjgoire ) It goes on forever... Whereas i already have the properties inside my class... So was just wondering if it could be done..
You might use a lambda:
FuncCall( []{ Foo f; f.Bar = "sausage"; f.Boo = 4; return f; }() );
Live example
Foo has to have a constructor or be an aggregate type:
class Foo {
std::string bar;
int boo;
public:
Foo(std::string s, int i) : bar(std::move(s)), boo(i) {}
};
void FuncCall(std::unique_ptr<Foo> ptr) {}
int main() {
FuncCall(make_unique<Foo>("sausage", 4));
}
struct Foo {
std::string bar;
int boo;
};
void FuncCall(std::unique_ptr<Foo> ptr) {}
int main() {
std::unique_ptr<Foo> foo(new Foo{"sausage", 4});
FuncCall(foo);
}
Or you can avoid pointers:
void FuncCall(Foo foo) {}
int main() {
FuncCall({sausage", 4});
}
Be aware that the following:
class Foo {
std::string m_bar = "Bar";
int m_baz = 3;
float m_boo = 4.2;
/* ... */
public:
Foo() {} // or Foo() = default or elision
};
int main() {
Foo f;
f.m_bar = "wunderBar";
}
Expands out to be along the lines of the following:
Foo* fptr = stack_allocate<Foo*>(sizeof(Foo));
// from ctor
fptr->m_bar.string("Bar"); // construct m_bar
fptr->m_baz.int(3);
fptr->m_boo.float(4.2);
// your code:
fptr->m_bar.operator=("wunderBar");
For similar reasons, you might want to look at the IL instructions for your C# construct - you'll find it's performing equally redundant operations (and in more complex situations, possibly boxing/unboxing).
Your C++ approach will also fail you when you incorporate non-copyable or non-movable types which will force you to pass pointers and/or bend your design.
What it /seems/ you are trying to do is recreate Python's optional parameters:
# C++-alike
class Foo(object):
def __init__(self, Bar, Baz, Boo):
...
# C#-alike:
class Foo(object):
def __init__(self, Bar="Bar", Baz=13, Boo=4.2):
...
C++ doesn't provide a direct way of doing this, the closest mechanisms are default parameters and operator overloading:
class Foo {
std::string m_bar = "Bar";
int m_baz = 3;
float m_boo = 4.2;
public:
Foo(std::string bar="Bar", int baz=3, int boo=6.1)
: m_bar(bar), m_baz(baz), m_boo(boo)
{}
/* Foo* f = new Foo(); => new Foo(bar="Bar", baz=13, boo=6.1);
* Foo* f = new Foo("hello"); => new Foo(bar="hello", baz=3, boo=4.2);
* Foo* f = new Foo("hello", 1, 1.); => new Foo(bar="hello", baz=1, boo=1.);
* Foo* f = new Foo(42.); => invalid, arguments must be in order.
*/
};
or
class Foo {
std::string m_bar = "Bar";
int m_baz = 3;
float m_boo = 4.2;
public:
Foo() = default;
// allow Foo("hello")
Foo(const char* bar) : m_bar(bar) {}
Foo(const std::string& bar) : m_bar(bar) {}
Foo(std::string&& bar) : m_bar(std::forward(bar)) {}
// allow Foo(10, 12.)
explicit Foo(int baz, float boo) : m_baz(baz), m_boo(boo) {}
/* Foo* f = new Foo(); => new Foo(bar="Bar", baz=3, boo=4.2);
* Foo* f = new Foo("hello"); => new Foo(bar="hello", baz=3, boo=4.2);
* Foo* f = new Foo(1, 1.); => new Foo(bar="Bar", baz=1, boo=1.);
* Foo* f = new Foo(42.); => invalid, no match
*/
};
See http://ideone.com/yFIqlA for SSCE.
If you genuinely have a dozen different constructor configurations, you should probably rethink your design.
--- Edit ---
Note: It's not compulsory that you expose all parameters in the constructor:
class Foo {
std::string m_user_supplied;
std::time_t m_time;
public:
Foo() : m_user_supplied(), m_time(0) {}
Foo(std::string src) : m_user_supplied(src), m_time(0) {}
void addTime(time_t inc) { m_time += inc; }
};
--- Edit 2 ---
"should maybe rethink your design" ... One problem with large, optional lists of parameters is growth. You are likely to wind up with parameters that depend on each other, contradict each other or interact with each other. You can either choose not to validate these or you can end up with complicated constructors.
struct Foo {
...
FILE* m_output;
const char* m_mode;
...
Foo(..., FILE* output, const char* mode, ...)
{
...
if (output != nullptr) {
ASSERT( output == nullptr || mode != nullptr );
... other requirements
} else {
if (mode != nullptr)
... might not be an error but it might be a bug ...
}
...
}
};
One approach to avoiding this is to use encapsulation/aggregation of related members.
class Foo {
...
struct FileAccess {
FILE* m_file;
const char* m_mode;
constexpr FileAccess() : m_file(nullptr), m_mode(nullptr) noexcept {}
FileAccess(FILE* file, const char* mode) : m_file(file), m_mode(mode) {
if (file == nullptr || mode == nullptr)
throw invalid_argument("file/mode cannot be null");
}
};
...
FileAccess m_access;
Foo(..., FileAccess access, ...);
};
This can go a fair way to reducing the bloat. If your API is stable, you can use it with initializer lists (if your API is not stable and you do change will bite you in the ass)
auto fooWithFile = make_unique<Foo>{..., /*access=*/{stdout, "w"}, ...};
auto fooWithout = make_unique<Foo>{..., /*access=*/{}, ...};
If you subsequently decide to stop using ctors and switch to using setters, this will translate reasonably well, since you can have overloaded "set" which takes one of the various configuration structs:
auto foo = make_unique<Foo>();
foo->set(FileAccess(stdout, "w"))
->set(Position(Right, -100, Top, 180))
->set(DimensionPercentage(80, 75));
vs
auto foo = make_unique<Foo>() { # pseudo based on if C++ had the C# syntax
m_file = stdout;
m_mode = "w";
m_xPosition = -100;
m_xPositionRel = Right;
m_yPosition = -180;
m_yPositionRel = Top;
m_dimensionType = Percentage;
m_xDimension = 80;
m_yDimension = 75;
};
You can use uniform initialization to initialize it.