template<class T>
struct broker
{
typedef T typeBroker;
static std::vector<std::string> extractListBroker(const std::string& broker)
{
std::vector<std::string> vec;
if(broker.empty())
{
for(int i=0;i<typeBroker::nbBroker;++i)
vec.push_back( typeBroker::listBroker[i] );
}
else
{
typedef boost::tokenizer<boost::char_separator<char> > my_tok;
boost::char_separator<char> sep( ";" );
my_tok tok( broker, sep );
for ( my_tok::const_iterator i = tok.begin(); i != tok.end(); ++i )
vec.push_back( *i );
}
return vec;
}
std::string brokerToStr(typename typeBroker::BROKER i) //<--Problem here !!
{
return typeBroker::listBroker[i];
}
};
struct brokerDisTradable : broker<brokerDisTradable>{
std::vector<std::string> listBroker;
brokerDisTradable()
{
listBroker.push_back("BRIDGE1" );
listBroker.push_back("BRIDGELONDON" );
listBroker.push_back("RECY" );
listBroker.push_back("CURRENEX" );
}
static const int nbBroker = 2;
enum BROKER { BRIDGE1, BRIDGELONDON, RECY, CURRENEX };
};
errro : error C2039: 'BROKER' : is not a member of broker_def::brokerDisTradable'
any idea?
Thanks!
You cannot use the derived type's internal types in the function declaration of the base, because the derived type's internal types aren't yet defined, the derived type is only declared.
There are a number of ways to get around this, including type traits parameter and additional template parameter, and they are perfectly discussed in Base's using a type defined in Derived, in a Curiously Recurring Template Pattern of comp.lang.c++.moderated: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/a99148265cb43680/b2581e058ffe8c91?#b2581e058ffe8c91
Since you're using the enum value as an index into an array, you could change the parameter type to brokerToStr to an int:
struct broker
{
typedef T typeBroker;
std::string brokerToStr(int i)
{
return typeBroker::listBroker[i];
}
Also, typeBroker::listBroker[i] won't work as listBroker is not a static member.
I don't understand why you are inheriting brokerDisTradable from border<brokerDisTradable>. Probably what you need to do is this:
struct brokerDisTradable {
std::vector<std::string> listBroker;
brokerDisTradable()
{
// ...
}
static const int nbBroker = 2;
enum BROKER { BRIDGE1, BRIDGELONDON, RECY, CURRENEX };
};
int main()
{
brokerDisTradable t;
broker<brokerDisTradable> b;
// ...
return 0;
}
A simplified example of the problem:
template <class T>
struct X
{
void foo(typename T::Enum);
};
struct Y: X<Y> //<-- X instantiate here, but at this point the compiler only knows
//that a struct called Y exists, not what it contains
{
enum Enum {Z};
};
As a possible workaround, perhaps move the enumeration out of Y and add a template parameter to X.
template <class T, class EnumType>
struct X
{
void foo(EnumType);
};
enum Y_Enum {Z};
struct Y: X<Y, Y_Enum>
{
};
brokerDisTradable : broker<brokerDisTradable> seems to be an incomplete type (infinite heritage inside)
struct brokerDisTradable and using broker<brokerDisTradable> will work..
Related
In some code that I was reading, I found the usage of empty struct like so:
struct input_iterator_tag { };
struct bidirectional_iterator_tag { };
struct random_access_iterator_tag { };
So in the rest of the code, it was used as what they call tag dispatching.
I was wondering if there is other usage of empty structs.
from an older post I saw that :
three major reasons we use empty structs in C++ are:
a base interface
a template parameter
a type to help overload resolution. (tag dispatching if I am not wrong)
Could someone explain that please?
a type to help overload resolution. (tag dispatching if I am not wrong)
When you want to use a complex template specialization pattern on some function, you don't try to go at it directly, but rather write:
template <typename T1, typename T2, other things maybe>
int foo(T1 param1, T2 param2 and so on)
{
using tag = put your complex stuff here, which produces an empty struct
detail::foo_impl(tag, std::forward<T1>(param1), std::forward<T2>(param2) and so on);
}
Now, the compiler doesn't have to decide between competing choices of template specialization, since with different tags you get incompatible functions.
a base interface
struct vehicle {
// common members and methods,
// including (pure) virtual ones, e.g.
virtual std::size_t num_maximum_occupants() = 0;
virtual ~vehicle() = default;
};
namespace mixins {
struct named { std::string name; };
struct wheeled { int num_wheels; public: rev() { }; };
} // namespace mixins
struct private_sedan : public vehicle, public wheeled, named {
// I dunno, put some car stuff here
//
// and also an override of `num_maximum_occupants()`
};
Making the base struct completely empty is perhaps not that common, but it's certainly possible if you use mixins a lot. And you could check for inheritance from vehicle (although I'm not sure I'd do that).
a template parameter
Not sure what this means, but venturing a guess:
template <typename T>
struct foo { };
template <typename T, typename N>
struct foo<std::array<T, N>> {
int value = 1;
};
If you now use foo<T>::value in a function, it will work only if T is int with few (?) exceptions.
I also tried to come up with examples:
as a base interface
// collection of very abstract vehicles
#include <vector>
struct Vehicle {};
struct Car : Vehicle {
int count_of_windows;
};
struct Bike : Vehicle {
int size_of_wheels;
};
std::vector<Vehicle> v{Bike{}, Car{}};
as a template parameter
// print same number in 3 different formats
#include <iostream>
struct dec {};
struct hex {};
struct octal {};
template<typename HOW = dec>
void print_me(int v);
template<>
void print_me<dec>(int v) {
auto f = std::cout.flags();
std::cout << std::dec << v << std::endl;
std::cout.flags(f);
}
template<>
void print_me<hex>(int v) {
auto f = std::cout.flags();
std::cout << std::hex << v << std::endl;
std::cout.flags( f );
}
template<>
void print_me<octal>(int v) {
auto f = std::cout.flags();
std::cout << std::oct << v << std::endl;
std::cout.flags(f);
}
int main() {
print_me(100);
print_me<hex>(100);
print_me<octal>(100);
}
a type to help overload resolution
// add a "noexcept" qualifier to overloaded function
// the noexcept version typically uses different functions
// and a custom "abort" handler
#include <iostream>
struct disable_exceptions {};
void is_number_1() {
int v;
std::cin >> v;
if (v != 1) {
throw new std::runtime_error("AAAA");
}
}
void is_number_1(disable_exceptions) noexcept {
int v;
// use C function - they don't throw
if (std::scanf("%d", &v) != 1) {
std::abort();
}
if (v != 1) {
std::abort();
}
}
int main() {
is_number_1();
is_number_1(disable_exceptions());
}
The example about "tag dispatching" can be found on cppreference iterator_tags. The iterator_category() member of an iterator is used to pick a different overload. That way you could write a different algorithm if for example iterator is forward_iterator, where you can only go forward, or it is a bidirectional_iterator, where your algorithm could change because you may walk back.
#include <iostream>
#include <string>
#include <vector>
#include <map>
std::vector<std::pair<std::string, [type of the object, entity or banana]>> nep; //[type of the object, entity or banana] is my imaginary type
class Entity
{
private:
int x;
public:
Entity(const int x) : x(x) {};
int GetX() const { return x; };
};
class Banana
{
private:
int y;
public:
Banana(const int y) : y(y) {};
int GetY() const { return y; };
};
[type of the object, entity or banana] CreateObj(std::string name) //Used that imaginary variable here again
{
for (unsigned short int i = 0; i < nep.size(); i++)
{
if (nep.at(i).first == name)
{
return [new object with type = nep.at(i).second];
}
}
}
int main()
{
nep.push_back({ "ent", Entity });
nep.push_back({ "banan", Banana });
CreateObj(banan).GetY();
std::cin.get();
}
[type of the object, entity or banana] is my imaginary variable-type thing.
What I'd like to do is pass there a class for example, and then using CreateObj() function I'd like to create new object of that type and use it.
How can I do that?
Short answer: no
Long answer:
You have tools like std::type_index and typeid, but they won't do what you want.
You can however store factory function instead of a type:
using result = std::any; // or some other common type
std::map<std::string, std::function<std::any()>> nep;
nep["banana"] = []{ return Banana{}; };
nep["entity"] = []{ return Entity{}; };
// Call the functions:
result my_banana = nep["banana"]();
Banana& b = std::any_cast<Banana&>(my_banana);
The functions stored in the map create instances of a known type. Since the map has to store functions of the same type, it must be returned through a common type. That common type can be std::any, std::variant<Banana, Entity> or a pointer to a base class.
Then you can search the map for a factory function and call it to get the created object. It must be unwrapped correctly to access the variable through the right type to access members.
If you do not want to use polymorphism, you can do something with meta-programming:
enum class ClassType {
EntityType,
BananaType,
};
namespace internal {
template <ClassType Type>
struct _build_type {};
template <>
struct _build_type<ClassType::EntityType> {
constexpr auto operator()() {
return EntityType();
}
};
template <>
struct _build_type<ClassType::BananaType> {
constexpr auto operator()() {
return BananaType();
}
};
}
And then, your construct object:
template <ClassType Type>
constexpr auto create_instance() {
return internal::_build_type<Type>{}();
}
So you can do:
const auto object = create_instance<BananaType>();
This thing will increase your compilation time but it does not have any performance penalty during runtime.
Consider the following two classes:
class LunchBox
{
public:
std::vector<Apple> m_apples;
};
and
class ClassRoom
{
public:
std::vector<Student> m_students;
};
The classes are alike in that they both contain a member variable vector of objects; however, they are unalike in that the vector's objects are different and the member variables have different names.
I would like to write a template that takes either LunchBox or ClassRoom as a template argument (or some other parameter) and an existing object of the same type (similar to a std::shared_ptr). The template would return an object that adds a getNthElement(int i); member function to improve accessing the methods. Usage would be like:
// lunchBox is a previously initialized LunchBox
// object with apples already pushed into m_apples
auto lunchBoxWithAccessor = MyTemplate<LunchBox>(lunchBox);
auto apple3 = lunchBoxWithAccessor.getNthElement(3);
I would like to do this without writing template specializations for each class (which likely would require specifying the member variable to operate on in some way). Preferably, I do not want to modify the LunchBox or ClassRoom classes. Is writing such a template possible?
You can minimize the amount of code that has to be written for each class -- it doesn't have to be a template specialization and it doesn't have to be an entire class.
class LunchBox
{
public:
std::vector<Apple> m_apples;
};
class ClassRoom
{
public:
std::vector<Student> m_students;
};
// you need one function per type, to provide the member name
auto& get_associated_vector( Student& s ) { return s.m_apples; }
auto& get_associated_vector( ClassRoom& r ) { return r.m_students; }
// and then the decorator is generic
template<typename T>
class accessor_decorator
{
T& peer;
public:
auto& getNthElement( int i ) { return get_associated_vector(peer).at(i); }
auto& takeRandomElement( int i ) { ... }
// many more ways to manipulate the associated vector
auto operator->() { return &peer; }
};
LunchBox lunchBox{};
accessor_decorator<LunchBox> lunchBoxWithAccessor{lunchBox};
auto apple3 = lunchBoxWithAccessor.getNthElement(3);
The simple helper function overload should ideally be in the same namespace as the type, to make argument-dependent lookup work (aka Koenig lookup).
It's also possible to specify the member at the point of construction, if you prefer to do that:
template<typename T, typename TMemberCollection>
struct accessor_decorator
{
// public to make aggregate initialization work
// can be private if constructor is written
T& peer;
TMemberCollection const member;
public:
auto& getNthElement( int i ) { return (peer.*member).at(i); }
auto& takeRandomElement( int i ) { ... }
// many more ways to manipulate the associated vector
auto operator->() { return &peer; }
};
template<typename T, typename TMemberCollection>
auto make_accessor_decorator(T& object, TMemberCollection T::*member)
-> accessor_decorator<T, decltype(member)>
{
return { object, member };
}
LunchBox lunchBox{};
auto lunchBoxWithAccessor = make_accessor_decorator(lunchBox, &LunchBox::m_apples);
auto apple3 = lunchBoxWithAccessor.getNthElement(3);
A simple way to do this is define a trait struct that has specializations with just the information that makes each case different. Then you have a template class that uses this traits type:
// Declare traits type. There is no definition though. Only specializations.
template <typename>
struct AccessorTraits;
// Specialize traits type for LunchBox.
template <>
struct AccessorTraits<LunchBox>
{
typedef Apple &reference_type;
static reference_type getNthElement(LunchBox &box, std::size_t i)
{
return box.m_apples[i];
}
};
// Specialize traits type for ClassRoom.
template <>
struct AccessorTraits<ClassRoom>
{
typedef Student &reference_type;
static reference_type getNthElement(ClassRoom &box, std::size_t i)
{
return box.m_students[i];
}
};
// Template accessor; uses traits for types and implementation.
template <typename T>
class Accessor
{
public:
Accessor(T &pv) : v(pv) { }
typename AccessorTraits<T>::reference_type getNthElement(std::size_t i) const
{
return AccessorTraits<T>::getNthElement(v, i);
}
// Consider instead:
typename AccessorTraits<T>::reference_type operator[](std::size_t i) const
{
return AccessorTraits<T>::getNthElement(v, i);
}
private:
T &v;
};
A few notes:
In this case, the implementation would technically be shorter without a traits type; with only specializations of Accessor for each type. However, the traits pattern is a good thing to learn as you now have a way to statically reflect on LunchBox and ClassRoom in other contexts. Decoupling these pieces can be useful.
It would be more idiomatic C++ to use operator[] instead of getNthElement for Accessor. Then you can directly index the accessor objects.
AccessorTraits really isn't a good name for the traits type, but I'm having trouble coming up with anything better. It's not the traits of the accessors, but the traits of the other two relevant classes -- but what concept even relates those two classes? (Perhaps SchoolRelatedContainerTraits? Seems a bit wordy...)
You said:
I would like to do this without writing template specializations for each class
I am not sure why that is a constraint. What is not clear is what else are you not allowed to use.
If you are allowed to use couple of function overloads, you can get what you want.
std::vector<Apple> const& getObjects(LunchBox const& l)
{
return l.m_apples;
}
std::vector<Student> const& getObjects(ClassRoom const& c)
{
return c.m_students;
}
You can write generic code that works with both LaunchBox and ClassRoom without writing any other specializations. However, writing function overloads is a form of specialization.
Another option will be to update LaunchBox and ClassRoom with
class LunchBox
{
public:
std::vector<Apple> m_apples;
using ContainedType = Apple;
};
class ClassRoom
{
public:
std::vector<Student> m_students;
using ContainedType = Apple;
};
and then, take advantage of the fact that
LaunchBox b;
std::vector<Apple>* ptr = reinterpret_cast<std::vector<Apple>*>(&b);
is a legal construct. Then, the following class will work fine.
template <typename Container>
struct GetElementFunctor
{
using ContainedType = typename Container::ContainedType;
GetElementFunctor(Container const& c) : c_(c) {}
ContainedType const& getNthElement(std::size_t n) const
{
return reinterpret_cast<std::vector<ContainedType> const*>(&c_)->operator[](n);
}
Container const& c_;
};
and you can use it as:
LunchBox b;
b.m_apples.push_back({});
auto f = GetElementFunctor<LunchBox>(b);
auto item = f.getNthElement(0);
I did a test case sample using a few basic classes:
class Apple {
public:
std::string color_;
};
class Student {
public:
std::string name_;
};
class LunchBox {
public:
std::vector<Apple> container_;
};
class ClassRoom {
public:
std::vector<Student> container_;
};
However for the template function that I wrote I did however have to change the name of the containers in each class to match for this to work as this is my template function:
template<class T>
auto accessor(T obj, unsigned idx) {
return obj.container_[idx];
}
And this is what my main looks like:
int main() {
LunchBox lunchBox;
Apple green, red, yellow;
green.color_ = std::string( "Green" );
red.color_ = std::string( "Red" );
yellow.color_ = std::string( "Yellow" );
lunchBox.container_.push_back(green);
lunchBox.container_.push_back(red);
lunchBox.container_.push_back(yellow);
ClassRoom classRoom;
Student s1, s2, s3;
s1.name_ = std::string("John");
s2.name_ = std::string("Sara");
s3.name_ = std::string("Mike");
classRoom.container_.push_back(s1);
classRoom.container_.push_back(s2);
classRoom.container_.push_back(s3);
for (unsigned u = 0; u < 3; u++) {
auto somethingUsefull = accessor(lunchBox, u);
std::cout << somethingUsefull.color_ << std::endl;
auto somethingElseUsefull = accessor(classRoom, u);
std::cout << somethingElseUsefull.name_ << std::endl;
}
return 0;
}
I'm not sure if there is a work around to have a different variable name from each different class this function can use; but if there is I haven't figured it out as of yet. I can continue to work on this to see if I can improve it; but this is what I have come up with so far.
I want to write a function that return different types based on different input as below.
enum MyType
{
A,
B
};
template<MyType T> struct MyStruct
{
};
static auto createMyStruct(MyType t)
{
if(t==A)
return MyStruct<A>();
else
return MyStruct<B>();
}
It didn't work out because there are two return types for one auto. Is there any other way to do this?
There is absolutely no way of having a (single) function that returns different types based on a runtime decision. The return type has to be known at compile time. However, you can use a template function, like this (thanks to #dyp for making me simplify the code):
#include <iostream>
#include <typeinfo>
enum MyType
{
A,
B
};
template<MyType>
struct MyStruct {};
template<MyType type>
MyStruct<type> createMyStruct()
{
return {};
}
int main()
{
auto structA = createMyStruct<A>();
auto structB = createMyStruct<B>();
std::cout << typeid(structA).name() << std::endl;
std::cout << typeid(structB).name() << std::endl;
}
I am assuming you want to write code like this:
void foo (MyType t) {
auto x = createMyStruct(t);
//... do something with x
}
You are attempting to derive the right type for x at runtime. However, the return type of a function must be known at compile time, and the type resolution for auto is also determined at compile time.
You could instead restructure your code to be like this:
template<MyType T> struct MyStruct
{
//...
static void foo () {
MyStruct x;
//... do something with x
}
};
The idea is to write a single foo() function whose only difference is the type of thing it is manipulating. This function is encapsulated within the type itself. You can now make a runtime decision if you have a mapping between MyType and MyStruct<MyType>::foo.
typedef std::map<MyType, void(*)()> MyMap;
template <MyType...> struct PopulateMyMap;
template <MyType T> struct PopulateMyMap<T> {
void operator () (MyMap &m) {
m[T] = MyStruct<T>::foo;
}
};
template <MyType T, MyType... Rest> struct PopulateMyMap<T, Rest...> {
void operator () (MyMap &m) {
m[T] = MyStruct<T>::foo;
PopulateMyMap<Rest...>()(m);
}
};
template<MyType... Types> void populateMyMap (MyMap &m) {
PopulateMyMap<Types...>()(m);
}
//...
populateMyMap<A, B>(myMapInstance);
Then, to make a runtime decision:
void foo (MyType t) {
myMapInstance.at(t)();
}
I think you should learn abstract factory design pattern.
For use objects of type MyStruct<A> or MyStruct<B> you need common interface.
Common interface provided in abstract base class.
struct MyStruct
{
virtual ~MyStruct() {}
virtual void StructMethod() = 0;
};
struct MyStructA: public MyStruct
{
void StructMethod() override {}
};
struct MyStructB: public MyStruct
{
void StructMethod() override {}
};
std::unique_ptr<MyStruct> createMyStruct(MyType t)
{
if (t==A)
return std::make_unique<MyStructA>();
else
return std::make_unique<MyStructB>();
}
I am trying to create a Container class where I can retrieve an object from the container by using that objects member variable as its identifier. But I get a compile error because I am trying to store a pointer(?)/reference to the objects member variable
template <typename Object>
class Container
{
private:
template <typename dataType>
dataType Object::* memberVariable; // error here "data member 'memberVariable' cannot be a member template"
template <typename dataType>
std::map <dataType, Object*> instanceVarMap; // what would be more efficient; a Map or unordered_map? I heard that
std::map <unsigned int, Object*> instanceIntMap; // ...unordered_maps use more memory & Maps are better when integers are the keys
public;
template <typename dataType>
Collection( dataType Object::*nMemberVariable )
{
memberVariable = nMemberVariable;
}
template <typename dataType>
Object* operator[] ( dataType nParam )
{
// do I need to check whether the element already exists or does
// stl already do this for me?
if ( instanceVarMap.find(nParam) == instanceVarMap.end() )
{
return NULL;
}
return instanceVarMap[ nParam ];
}
Object* operator[] ( unsigned int nParam )
{
if ( instanceIntMap.find(nParam) == instanceIntMap.end() )
{
return NULL;
}
return instanceIntMap[ nParam ];
}
void store( Object* o )
{
if ( o==NULL || instanceMap.contains(o->memeberVariable) != instanceMap.end() ) { return; }
instanceIntMap.insert( o->ID, o );
instanceVarMap.insert( o->memberVariable, o ); // is this the correct way I get the objects member variable? o->memberVariable
}
};
// I am doing this so I can use the class like so
struct FoodItem
{
unsigned int ID;
string name;
double price;
};
Collection <FoodItem*> foodCol( &FoodItem::name );
// after storing some FoodItems in foodCol, I can retreive a FoodItem either
// by their ID or their name
FoodItem* f = foodCol["coffee"]; // find FoodItem by their member variable 'name'
FoodItem* g = foodCol[1]; // find FoodItem by their ID var
Declaring a template data member is not allowed in C++ (not to confuse with template syntax used while defining a static member). The best way to achieve is,
template <typename Object, typename dataType> // <-- Add dataType here
class Container
{
private:
dataType Object::* memberVariable; // use 'dataType' simply
// ...
};
template <typename dataType>
dataType Object::* memberVariable; // error
Declaring a tempate data member? That is not allowed by C++. And I cannot you suggest any alternative, because I don't actually understand what exactly you're trying to do.
Why don't you first try using containers provided by the Standard Library? Have you seen std::vector, std::list, std::map etc, along with generic functions from <algorithm>?
In the following there are two variations of what you are asking for: the first in which the member is a template parameter, and the second in which the member is instead passed as argument when building the map...
#include <map>
#include <string>
#include <iostream>
template<typename Object, typename MemberType, MemberType Object::*member>
struct MemberMap
{
std::map<MemberType, Object *> mmap;
Object * operator[](const MemberType& mv) const
{
typename std::map<MemberType, Object *>::const_iterator i = mmap.find(mv);
return i == mmap.end() ? NULL : i->second;
}
void store(Object *o)
{
if (o && mmap.find(o->*member) == mmap.end())
mmap[o->*member] = o;
}
};
template<typename Object, typename MemberType>
struct MemberMapByInst
{
MemberType Object::*member;
std::map<MemberType, Object *> mmap;
MemberMapByInst(MemberType Object::*member) : member(member)
{
}
Object * operator[](const MemberType& mv) const
{
typename std::map<MemberType, Object *>::const_iterator i = mmap.find(mv);
return i == mmap.end() ? NULL : i->second;
}
void store(Object *o)
{
if (o && mmap.find(o->*member) == mmap.end())
mmap[o->*member] = o;
}
};
struct Foo
{
std::string name;
Foo(const std::string& name) : name(name)
{
}
};
int main()
{
Foo foo1("This is a test");
Foo foo2("This is another test");
MemberMap<Foo, std::string, &Foo::name> namemap;
namemap.store(&foo1);
namemap.store(&foo2);
MemberMapByInst<Foo, std::string> namemap2(&Foo::name);
namemap2.store(&foo1);
namemap2.store(&foo2);
std::cout << (namemap["This is a test"] != NULL) << std::endl;
std::cout << (namemap["What about this?"] != NULL) << std::endl;
std::cout << (namemap2["This is a test"] != NULL) << std::endl;
std::cout << (namemap2["What about this?"] != NULL) << std::endl;
return 0;
}
Basically you need to move at least the member type out as a template parameter because that is needed to be able to generate the C++ code of the map. You can decide at runtime what is the member you want to use as key (second version), but its type must be fixed at compile time.
If instead even the actual member you want to use as key is known a compile time then the member pointer can be factored out as a template parameter (first version), generating more efficient code (however creating a new class for every different member - thus increasing compiled code size).
you can get away by declaring a member type like this.
struct MyObject
{
int Variable;
typedef int MyObject::* ObjectVariablePtrType;
};
template<typename Object>
class Container
{
typename Object::ObjectVariablePtrType memberVariable;
};