When using the std::for_each,
class A;
vector<A*> VectorOfAPointers;
std::for_each(VectorOfAPointers.begin(), VectorOfAPointers.end(), std::mem_fun(&A::foo));
If we have classes inheriting from A and implementing foo(), and we hold a vector of pointers to A,
is there any way to call a polymorphic call on foo(), rather then explicitly calling A::foo()?
Note: I can't use boost, only standard STL.
Thanks,
Gal
It actually works this way.
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
struct A {
virtual void foo() {
std::cout << "A::foo()" << std::endl;
}
};
struct B: public A {
virtual void foo() {
std::cout << "B::foo()" << std::endl;
}
};
int main()
{
std::vector<A*> VectorOfAPointers;
VectorOfAPointers.push_back(new B());
std::for_each(VectorOfAPointers.begin(), VectorOfAPointers.end(), std::mem_fun(&A::foo));
return 0;
}
prints
B::foo()
So it does exactly what you want. Check that virtual keywords are present though, it's easy to forget them.
Related
Can I send an instance to a function not by using the . operator?
For example:
// header file
class A
{
public:
void foo() {std::cout << "Hello" << std::endl;}
};
// main file
A instance = new A;
instance.foo();
// instead do something like this
A::foo(instance);
Can I do something like that?
Yes, you can indirectly via std::invoke:
#include <functional>
#include <iostream>
struct A {
void foo() {
std::cerr << "hi\n";
}
};
int main() {
A a;
std::invoke(&A::foo,a);
}
But std::invoke's implementation will internally probably just apply the .* operator.
You're more than welcome to use the pointer to member syntax.
A instance;
auto fn = &A::foo;
(instance.*fn)();
.* is a different operator than .. Whether this is more readable is left as an exercise to the reader (hint: it's not)
I want to store 6 pointers to objects. But the Pointers can be in any order and point to different instances of (12) subclasses of one superclass, so they are possibly all of different types.
Arrays and such don't work, because the superclass is virtual.
Vectors and Tuples don't work, because the datatypes are of no specific order and are not known at compile time.
Im fairly new to C++ and I'm running out of Ideas.
Here some code to elaborate the problem:
baseclass{
getfoobar()=0;
}
subclass1{
getfoobar(){...}
}
subclass2{
getfoobar(){...}
}
---
#include <otherclasses.h>
memoryclass{
baseclass mem[6];
}
is basically what im trying.
You CAN create a vector of superclass pointers. It will achieve what you want, as it will call the overwritten function. This is of course assuming you are talking about inheritance, like:
#include <vector>
using type = ????;
class A {
virtual type foo() = 0;
}
class B : A {
type foo() override { ... }
}
class C : A {
type foo() override { ... }
}
int main(){
std::vector<A*> arr;
arr.push_back(new B);
arr.push_back(new C);
}
Now if I misunderstood and this doesn't work for some reason (i.e. they just share the function and are not actually related classes), you can do something like this, but it is not very nice:
#include <concepts>
#include <vector>
#include <functional>
using type = ?????;
template <class T> requires requires(T t){
{ t.foo() } -> std::same_as<type>;
}
std::function<type()> getFunction(T* t){
return [t](){ return t->foo(); };
}
int main(){
std::vector<std::function<type()>> arr;
arr.push_back(getFunction(new B));
arr.push_back(getFunction(new C));
}
I don't recommend this over the first option unless you have very good reason to do this.
Note: Since you didn't specify return type I winged it with ?????
Also: In the second you can replace template<class T> requires ... std::function<type()>, with just template<class T> std::function<type()>, if the compiler doesn't like #include <concepts>
You can try std::set<Superclass*>. Use pointers to your base superclass instead pointers to particular subclasses.
Actually I used std::shared_ptr<> smart pointer template to avoid raw memory management.
Example code:
#include <cstdlib>
#include <string>
#include <sstream>
#include <set>
#include <memory>
#include <iostream>
class baseclass {
public:
virtual std::string getfoobar() = 0;
};
typedef std::shared_ptr<baseclass> baseclass_ptr;
class subclass1 : public baseclass{
public:
std::string getfoobar() override {
return "from subclass1";
}
};
class subclass2 : public baseclass{
public:
std::string getfoobar() override {
return "from subclass2";
}
};
int main(int argc, char** argv) {
// Use current time as seed for random generator
std::srand(static_cast<unsigned>(std::time(nullptr)));
std::set<baseclass_ptr> container;
// Randomly generate number of elements
const int random_count = std::rand() % 10 + 1;
for (int i = 0; i < random_count; ++i) {
// Randomly create subclass1 or subclass2
if (std::rand() % 2) {
container.insert(std::make_shared<subclass1>());
}
else {
container.insert(std::make_shared<subclass2>());
}
}
// Iterate resulting container
std::cout << "size = " << container.size() << std::endl;
for (auto iterator : container) {
std::cout << "getfoobar(): " << iterator->getfoobar() << std::endl;
}
return 0;
}
Does std::future in c++ support polymorphism?
So, if to store child_class in future<parent_class>, can I after get it after by dynamic_cast<child_class>?
Providing you use a reference or a pointer (probably obvious since it'll fail to compile otherwise)... Yes.
#include <iostream>
#include <future>
using namespace std;
struct Parent {
virtual void a() { cout << "I am parent"; }
};
struct Child : Parent {
virtual void a() { cout << "I am child"; }
};
Child g_c; //just some global for the purposes of the example
int main() {
std::future<Parent&> p = async(launch::async, []() -> Parent& { return g_c; });
auto c = dynamic_cast<Child&>(p.get());
c.a();
return 0;
}
code result here: http://ideone.com/4Qmjvc
I am trying to do something I thought was simple: calling functions that call functions that call functions (from inherited classes) using a chain of pointers. Is there a better way of accomplishing this? Also, in the spirit of C++11, how would I incorporate smart pointers in this example? This example crashes the application:
Here is the sample code, apologies if it looks a little silly:
Actual output (Crashes!):
almost there...
Desired output:
almost there...
hello from function1
f1.h:
#ifndef FUNCTION_1_H
#define FUNCTION_1_H
//f1.h (header file)
#include <iostream>
struct f1{
int _a;
f1() {}
void function1();
};
#endif
f2.h:
#ifndef FUNCTION_2_H
#define FUNCTION_2_H
//f2.h (header file)
#include "f1.h"
struct f2 : public f1{
int _b;
f1* f1_ptr;
f2() :f1(){}
void function2();
};
#endif
f3.h:
#ifndef FUNCTION_3_H
#define FUNCTION_3_H
#include "f2.h"
struct f3 :public f2{
int _c;
f2* f2_ptr;
f3() : f2(){}
void function3();
};
#endif
CPPs:
f3.cpp:
#include "f3.h"
void f3::function3(){
//do stuff...
//e.g. calculate an int Var3
f2_ptr->function2(/*pass Var3 as argument*/);
}
f2.cpp:
#include "f2.h"
void f2::function2(/*receive Var3*/){
//do stuff with Var3
//e.g. maybe use Var3 to calculate an int Var2
std::cout << "almost there..." << std::endl;
f1_ptr->function1(/*pass Var2 as argument*/);
}
f1.cpp:
#include "f1.h"
void f1::function1(/*receive Var2*/){
//take Var2 and use elsewhere
//or continue linking to other functions
std::cout << "hello from function1" << std::endl;
}
main.cpp:
int main(){
f3* ptr3 = new f3;
ptr3->function3();
//delete ptr3;
std::cin.get();
return 0;
}
The problem is that in the upper classes, the pointers f2* and f1* are not initialized, so when you do f2_ptr->function2(), you are trying to access a member function via an uninitialized pointer, which leads to UB (undefined behaviour). Your code is doing basically this:
#include <iostream>
using namespace std;
struct Base
{
void f(){cout << "In f" << endl;}
};
struct Derived
{
Base* ptr;
};
int main()
{
Derived* foo;
foo->ptr->f(); //cannot use foo->ptr, it is not initialized
}
So you have to make sure that in the constructors of f3 you initialize the f2_ptr and so on. About smart pointers, you can use std::unique_ptr or std::shared_ptr, the syntax is std::unique_ptr<Foo> pointer( new Foo ) (and similarly for std::shared). It is highly recommended to use them, for example, you HAVE TO initialize them (cannot arrived at this problem if you'd have used smart pointers)
Here is a hint for how to write f3.cpp:
#include "f3.h"
// define the constructor here (and just declare it in the header `f3.h`)
f3::f3() : f2()
{
auto f2_ptr = std::make_shared<f2>();
// and all our nightmares are over, f2_ptr is now a valid pointer
// which will automatically release the allocated memory
// when the reference count is zero
}
void f3::function3()
{
//do stuff...
//e.g. calculate an int Var3
f2_ptr->function2(/*pass Var3 as argument*/);
}
And since I started this, here is a full C++11 example (it uses in-class initialization) with chaining and that uses smart pointers, which works and is basically equivalent to yours:
#include <iostream>
#include <memory>
using namespace std;
struct Base
{
void f_base()
{
cout << "In f_base" << endl;
}
};
struct Derived
{
void f_derived()
{
cout << "In f_derived" << endl;
}
std::shared_ptr<Base> ptrBase = make_shared<Base>();
};
struct DerivedDerived
{
std::shared_ptr<Derived> ptrDerived = make_shared<Derived>();
};
int main()
{
DerivedDerived *foo = new DerivedDerived;
foo->ptrDerived->ptrBase->f_base(); // OK now
}
PS: this may help you understand what's going on
When does invoking a member function on a null instance result in undefined behavior?
I need to print the type of a parameter in a C++ source file using the clang API.
If I have a parameter representation in clang (ParmVarDecl* param) I can print the name of the parameter using param->getNameAsString(). I would need a method param->getTypeAsString(), but there is no such method. So is there another way to do this task?
Got the answer to my question in the llvm irc:
There is a method std::string clang::QualType::getAsString(SplitQualType split)
So this does work for me:
ParmVarDecl* param = *someParameter;
cout << QualType::getAsString(param->getType().split()) << endl;
You can use typeid to get the name of any type. Although it will vary from compiler to compiler, and may not be a pretty name.
#include <iostream>
#include <typeinfo>
struct MyStruct { };
int main()
{
std::cout << typeid(MyStruct).name() << std::endl;
}
If you need to do this for a lot of classes, you could make the call part of a base class, then any class that needs the functionality can just inherit from it.
#include <iostream>
#include <typeinfo>
class NamedClass
{
public:
virtual ~NamedClass() { }
std::string getNameAsString()
{
return typeid(*this).name();
}
};
class MyStruct : public NamedClass
{
};
int main()
{
MyStruct ms;
std::cout << ms.getNameAsString() << std::endl;
}