How to use Boost Variant with struct objects C++ - c++

I have two classes and depending on the nature of key, I would like to get the struct value out of the boost::variant. The code is listed below.
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
class A {
public:
struct greeting {
string hello;
};
class B {
public:
struct greeting {
string bye;
};
};
typedef boost::variant<A::greeting, B::greeting> greet;
greet getG(string key) {
greet g;
if (key == "A") {
g.hello = "MY ENEMY"; // this line doesn't work
}
else {
g.bye = "MY FRIEND"; // nor this line
}
return g;
};
int main() {
A a;
B b;
greet h = getG("A");
A::greeting my = boost::get<A::greeting>(h);
cout << my.hello << endl;
return 0;
}
The exact error that I am getting is:
error: no member named 'hello' in 'boost::variant<A::greeting, B::greeting, boost::detail::variant::void_, boost::detail::variant::void_, ...>' g.hello = "MY ENEMY"; and
error: no member named 'bye' in 'boost::variant<A::greeting, B::greeting, .../>' g.bye = "MY FRIEND";
Any help is appreciated.

The variant type doesn't have the .hello and .bye members. You can access them via a "visitor" function. But you still have to decide what to do when the visitor is not applied to the right type. I think you are not using Boost.Variant in the way that is intended to be used. (For example the conditionals don't smell well).
http://www.boost.org/doc/libs/1_61_0/doc/html/variant/reference.html#variant.concepts.static-visitor
struct hello_visitor : boost::static_visitor<>{
string const& msg;
hello_visitor(string const& msg) : msg(msg){}
void operator()(A::greeting& t) const{
t.hello = msg;
}
void operator()(B::greeting& t) const{
// throw? ignore? other?
}
};
struct bye_visitor : boost::static_visitor<>{
string const& msg;
bye_visitor(string const& msg) : msg(msg){}
void operator()(A::greeting& t) const{
// throw? ignore? other?
}
void operator()(B::greeting& t) const{
t.bye = msg;
}
};
greet getG(string key) {
greet g;
if (key == "A") { // is "key" handling the type, if so you can delegate this to the library instead of doing this.
boost::apply_visitor(hello_visitor("MY ENEMY"), g);
}
else {
boost::apply_visitor(bye_visitor("MY FRIEND"), g);
}
return g;
};

Related

Overloading subscript operator in a C++/WinRT runtimeclass

I am new authoring C++/WinRT runtime classes, and I was requested to overload the subscript operator ([ ]) for a runtime class Parameter. The class Parameter contains an IMap<hstring, IInspectable> that stores a set of parameters indexed by the parameter name.
Here is the code:
namespace winrt::Parameter::implementation
{
using namespace winrt;
using namespace Windows::Foundation::Collections;
struct Parameter : ParameterT<Parameter>
{
private:
IMap<hstring, IInspectable> m_Parameters{ nullptr };
public:
Parameter() { m_Parameters = single_threaded_map<hstring, IInspectable>(); }
~Parameter() {};
IInspectable& operator[](const hstring& key)
{
if (!m_Parameters.HasKey(key))
{
m_Parameters.Insert(key, {});
}
return m_Parameters.Lookup(key);
}
IInspectable const& operator[](const hstring& key) const
{
if (!m_Parameters.HasKey(key))
{
m_Parameters.Insert(key, {});
}
return m_Parameters.Lookup(key);
}
};
}
namespace winrt::Parameter::factory_implementation
{
struct Parameter : ParameterT<Parameter, implementation::Parameter>
{
};
}
The code above compiles with no errors, but I get the below error when I try to consume the Parameter code in a UWP C# test App:
Parameter parameter = new Parameter();
const string V = "test";
parameter[V] = "any test value";
string test = parameter[V];
Error CS0021 Cannot apply indexing with [ ] to an expression of type 'Parameter'
Does anyone have any ideas on what I am missing here?
The problem seems to be with the C++/WinRT version because this other similar code using standard C++/17 works as expected.
class Parameter
{
private:
std::map<std::string, std::any> m_Parameter{};
public:
std::any& operator[](const std::string& name);
};
std::any& Parameter::operator[](const std::string& key)
{
if (m_Parameter.find(key) == m_Parameter.end())
{
m_Parameter.insert({ key, {} });
}
return m_Parameter.at(key);
}
int main()
{
Parameter parameter{};
parameter["test"] = 'b';
parameter["other test"] = std::string("other test value");
std::cout << std::any_cast<std::string>(parameter["other test"]) << '\n';
std::cout << std::any_cast<char>(parameter["test"]) << '\n';
return 0;
}

How to create a specialized and default versions of a function that take base and derived classes?

I have the following class architecture:
class Animal
{
// ...
}
class Cat : public Animal
{
// ...
}
class Dog : public Animal
{
// ...
}
// + Several other derived classes
In another section of my code, I have a function that goes through a list of Animals and needs to perform specialized actions in the case of several of the derived classes and a default action otherwise. How can I handle this situation elegantly, given the following constraints:
I'd like to keep the new code outside of Animal and its derived
classes because of separation of concerns.
I'd like to avoid using a switch statement on types or enums as it feels very smelly.
Here's one way - use the concept-model idiom (my name):
#include <iostream>
#include <vector>
struct AnimalConcept {
virtual ~AnimalConcept() = default;
virtual void make_noise() const = 0;
};
// default case
void make_noise_for(const AnimalConcept&)
{
std::cout << "no noise" << std::endl;
}
template<class Model>
struct AnimalModel : AnimalConcept
{
void make_noise() const override {
make_noise_for(static_cast<const Model&>(*this));
}
};
// some models
struct Cat : AnimalModel<Cat>
{
};
struct Dog : AnimalModel<Dog>
{
};
struct Giraffe : AnimalModel<Giraffe>
{
};
// separation of concerns - specific overrides
void make_noise_for(const Cat&) {
std::cout << "meow\n";
}
void make_noise_for(const Dog&) {
std::cout << "woof\n";
}
// test
using namespace std;
int main(){
std::vector<std::unique_ptr<const AnimalConcept>> animals;
animals.emplace_back(new Cat);
animals.emplace_back(new Dog);
animals.emplace_back(new Giraffe);
for (const auto& p : animals) {
p->make_noise();
}
return 0;
}
expected output:
meow
woof
no noise
And here's another way to implement it (this one is nicer since it allows all animals to have unrelated interfaces):
#include <iostream>
#include <vector>
struct AnimalConcept {
virtual ~AnimalConcept() = default;
virtual void make_noise() const = 0;
};
// default case
template<class T>
void make_noise_for(const T&)
{
std::cout << "this animal makes no noise" << std::endl;
}
template<class Model>
struct AnimalModel : AnimalConcept
{
template<class...Args>
AnimalModel(Args&&...args)
: _model { std::forward<Args>(args)... }
{}
private:
void make_noise() const override {
make_noise_for(_model);
}
Model _model;
};
// some models
struct Cat
{
Cat(std::string name)
: _name { std::move(name) }
{}
const std::string& name() const {
return _name;
}
private:
std::string _name;
};
struct Dog
{
Dog(std::string name, int age)
: _name { std::move(name) }
, _age { age }
{}
const std::string& name() const {
return _name;
}
int age() const {
return _age;
}
private:
std::string _name;
int _age;
};
struct Giraffe
{
};
// separation of concerns - specific overrides
void make_noise_for(const Cat& c) {
std::cout << c.name() << " says meow\n";
}
void make_noise_for(const Dog& d) {
std::cout << "the dog called " << d.name() << " who is " << d.age() << " years old says woof\n";
}
// test
using namespace std;
int main(){
std::vector<std::unique_ptr<const AnimalConcept>> animals;
animals.emplace_back(new AnimalModel<Cat> { "felix" });
animals.emplace_back(new AnimalModel<Dog> { "fido", 2 });
animals.emplace_back(new AnimalModel<Giraffe>);
for (const auto& p : animals) {
p->make_noise();
}
return 0;
}
expected output:
felix says meow
the dog called fido who is 2 years old says woof
this animal makes no noise
You can use a combination of the following to get type based dispatch.
Provide for every class to return a type ID associated with it.
Provide a virtual function in the base class to get the type ID associated with an object.
Provide a way for registration of functions based on type ID.
When the time comes for execution of the top level function, search for a registered function given an animal's type ID. If a function is registered, call it. Otherwise, use the default function.
// Implement this function in a .cpp file.
int getNextTypeID()
{
static int typeID = 0;
return ++typeID;
}
class Animal
{
virtual int getTypeID();
};
class Cat : public Animal
{
static int getID()
{
static int typeID = getNextTypeID();
}
virtual int getTypeID()
{
return getID();
}
};
class Dog : public Animal
{
static int getID()
{
static int typeID = getNextTypeID();
}
virtual int getTypeID()
{
return getID();
}
};
foo.h:
typedef void (*AnimalFunction)(Animal& a);
int registerAnimalFunctor(int typeID, AnimalFunction f);
void foo(Animal& a);
foo.cpp:
typedef std::map<int, AnimalFunction> AnimalFunctionMap;
AnimalFunctionMap& getAnimalFunctionMap()
{
static AnimalFunctionMap theMap;
return theMap;
}
int registerAnimalFunctor(int typeID, AnimalFunction f)
{
getAnimalFunctionMap()[typeID] = f;
return 0;
}
void defaultAnimalFunction(a)
{
// Default action
}
void foo(Animal& a)
{
AnimalFunctionMap& theMap = getAnimalFunctionMap();
AnimalFunctionMap::iterator iter = theMap.find(a.getTypeID());
if ( iter != theMap.end() )
{
iter->second(a);
}
else
{
defaultAnimalFunction(a);
}
}
cat_foo.cpp:
void CatFunction(Animal& a)
{
// Cat action.
}
int dummy = registerAnimalFunctor(Cat::getID(), CatFunction);
dog_foo.cpp:
void DogFunction(Animal& a)
{
// Dog action.
}
int dummy = registerAnimalFunctor(Dog::getID(), DogFunction);

Is const_cast on pointer to member safe?

In the following code, a non-const method of an object calls a const-method of the same object that returns a const-pointer to the object's field, and then this returned pointer is casted to a non-const version — it's a technique similar to one in this answer: Elegant solution to duplicate, const and non-const, getters? [duplicate]. However, since I put pointers into a complex data structure, I am not sure it will actually work. Will it?
class Struct {
private:
Field f, g;
std::map<std::string, const FieldBase*> const_fields_t;
std::map<std::string, FieldBase*> fields_t;
public:
const_fields_t get_fields() const {
return const_fields_t { { "f", &f }, { "g", &g } };
}
fields_t get_fields() {
const Foo* = this;
fields_t result;
foreach(auto& v : const_this->get_fields()) {
result[v->first] = const_cast<FieldBase*>(v->second);
}
return result;
}
};
Yes, (I cleaned up your code a bit):
#include <string>
#include <functional>
#include <iostream>
#include <map>
using namespace std;
class FieldBase {public: virtual string get_data() = 0; };
class Field : public FieldBase { public: string data; virtual string get_data() { return data; } };
class Struct {
public:
Field f, g;
typedef std::map<std::string, const FieldBase*> const_fields_t;
typedef std::map<std::string, FieldBase*> fields_t;
public:
const_fields_t get_fields() const {
cout << "const get_fields() called" << endl;
return const_fields_t { { "f", &f }, { "g", &g } };
}
fields_t get_fields() {
cout << "non-const get_fields() called" << endl;
auto const_this = static_cast<const Struct*>(this);
fields_t result;
for(auto& v : const_this->get_fields()) {
result[v.first] = const_cast<FieldBase*>(v.second);
}
return result;
}
};
int main ()
{
Struct a;
a.f.data = "Hello";
a.g.data = "World";
Struct::fields_t obj = a.get_fields();
cout << obj["f"]->get_data() << endl;
cout << obj["g"]->get_data() << endl;
}
Live example
You basically have the const function act like a gateway to get the values you need and then cast away the constness. That will also work for your purpose since the pointers are going to be de-consted and stored in the new map.
Keep in mind that there might probably be a better solution not involving all the above copying around.

call functions depending on a string Parameter

I try to find a way to call functions depending on one String-Parameter.
Enums or Int are ok too for the Parametertype. Maybe there is something more ?
Is there a way to do it like this:
myFunction(string functionParameter, int value){
this->functionParameter(value);}
What is the best way for this? I know there are some similar Questions, but i didnt found a Answer that really fits my Problem.
Just use a map to map from strings to functions:
void f1()
{
std::cout << "f1!" << std::endl;
}
void f2()
{
std::cout << "f2!" << std::endl;
}
void f3()
{
std::cout << "f3!" << std::endl;
}
int main()
{
std::unordered_map<std::string,std::function<void()>> map;
map["f1"] = f1;
map["f2"] = f2;
map["f3"] = f3;
map["f1"]();
map["f2"]();
map["f3"]();
}
This outputs:
f1!
f2!
f3!
C++ doesn't have direct support to call functions using the name. You'll need to create the mapping somehow. The easiest approach is probably to create a map of a suitable std::function<...> type:
void f(int);
void g(int);
typedef std::function<void(int)> Function;
std:: map<std::string, Function> functions;
// ...
functions["f"] = f;
functions["g"] = g;
void call(std::string const& name, int x) {
auto it = functions.find(name);
if (it->second != functions.end()) {
it->second(x);
}
else {
// deal with unknown functions
}
}
You can map the string to the function pointer. Try something like this:
#include <iostream>
#include <string>
#include <functional>
#include <map>
class X;
template<class X>
class handler_factory;
template<>
class handler_factory<X>
{
private:
using HandlerType = void (X::*)(int);
public:
handler_factory();
HandlerType get(const std::string& name) const
{
if (handlers.find(name) == handlers.end())
return nullptr;
else
return (*handlers.find(name)).second;
}
private:
std::map<std::string, HandlerType> handlers;
};
class X
{
public:
friend class handler_factory<X>;
private:
void f(int);
void h(int);
};
handler_factory<X>::handler_factory()
{
handlers["f"] = &X::f;
handlers["h"] = &X::h;
}
void X::f(int) { std::cout << "X::f();"; }
void X::h(int) { std::cout << "X::h();"; }
Your class (in this example X) can have a function dispatch_method that looks like:
template<typename... Args>
void dispatch_method(const std::string& name, Args&&... args)
{
if (find_handler(name))
(this->*find_handler(name))(std::forward<Args>(args...));
}
Where find_handler is a helper method:
private:
auto find_handler(const std::string& name)
-> decltype(handler_factory<X>().get(name))
{
return handler_factory<X>().get(name);
}
Then you can call it like this:
int main()
{
X{}.dispatch_method("f", 5);
}
You may use something like:
#include <map>
#include <functional>
#include <stdexcept>
#include <string>
template<typename T> class Caller;
template<typename Ret, typename... Args>
class Caller<std::function<Ret(Args...)>>
{
public:
typedef std::function<Ret(Args...)> FuncType;
void add(const std::string& name, FuncType f)
{
functions[name] = f;
}
Ret call(const std::string& name, Args... args)
{
auto it = functions.find(name);
if (it == functions.end()) {
// Or any other error
throw std::runtime_error("unknown " + name + "function");
}
return (it->second)(args...);
}
private:
std::map<std::string, FuncType> functions;
};
So lets test it:
int minus(int a) { return -a; }
int main(int argc, char** argv)
{
Caller<std::function<int (int)>> caller;
caller.add("+1", [](int a) { return a + 1; } );
caller.add("minus", minus);
caller.call("minus", -42); // calls minus(-42), returns 42
caller.call("+1", 41); // calls the lambda, returns 42
return 0;
}
This is similar to question here. You need to create a map like this map<string, class::method>, then you can use its signature to search for function and call it.
Two ways are available for you:
1. Without using any 3rd-party library (in row C++):
#include <map>
#include <string>
struct Math
{
double sinFunc(double x) { return 0.33; };
double cosFunc(double x) { return 0.66; };
};
typedef double (Math::*math_method_t)(double);
typedef std::map<std::string, math_method_t> math_func_map_t;
int main()
{
math_func_map_t mapping;
mapping["sin"] = &Math::sinFunc;
mapping["cos"] = &Math::cosFunc;
std::string function = std::string("sin");
math_func_map_t::iterator x = mapping.find(function);
int result = 0;
if (x != mapping.end()) {
Math m;
result = (m.*(x->second))(20);
}
}
2. By using Boost library: The most convenient notation for method is function<signature> where function is either included in boost or in <utility>.
The signature would be like this.
map<string, function<double (double)> map; ...
map["sin"](1.0);

"no matching function" initializing class

I got that message
no matching function for call to 'main()::MySeqInFileEnumerator::MySeqInFileEnumerator(const char [10])'
when im doing my string matching job.I have to method override existing code.I have to open an input text, and make an abstract file from it, then i have to do an optimistic linsearch.
#include <iostream>
#include "linsearch.hpp"
#include "seqinfileenumerator.hpp"
using namespace std;
struct MyPair
{
int azon;
int osszeg;
friend ifstream& operator>>(ifstream& f, MyPair& df);
};
ifstream& operator>>(ifstream& f, MyPair& df)
{
f >> df.azon >> df.osszeg;
return f;
}`enter code here`
int main()
{
class MyLinSearch: public LinSearch <int, true>
{
bool Cond(const int& e) const
{
return e<=-100000;
}
};
class MySeqInFileEnumerator: public SeqInFileEnumerator <MyPair>
{
void Next()
{
MyPair dx;
f >> dx;
df.azon=dx.azon;
df.osszeg=dx.osszeg;
while(dx.azon==df.azon)
{
dx.osszeg+=df.osszeg;
f >> dx;
}
}
};
MyLinSearch pr;
MySeqInFileEnumerator t("input.txt");
pr.AddEnumerator(&t);
pr.Run();
if (pr.Found())
{
cout << "false " << endl;
}
else cout << "true" << endl;
return 0;
}
As the error message says, the class has no constructor taking a string; yet you try to use one with
MySeqInFileEnumerator t("input.txt");
Perhaps the base class has a suitable constructor? In that case, you'll need to forward the argument:
explicit MySeqInFileEnumerator(char const * name) :
SeqInFileEnumerator<MyPair>(name)
{}
You forgot to add a suitable constructor. Something like this:
class MySeqInFileEnumerator: public SeqInFileEnumerator<MyPair>
{
public:
MySeqInFileEnumerator(char const * p) : SeqInFileEnumerator<MyPair>(p) { }
// ...
};
(This is assuming your base class has a corresponding constructor. Modify to taste.