Examples of practical usage of Boost::MPL? - c++

Can you share any real-world examples of Boost::MPL usage (except lambdas), just to let me better understand its purposes and field of practical usage? The MPL documentation tutorial has a dimensional analysis example, but maybe because it's such an academic example it hasn't given me a feeling of Boost::MPL and when it can be effectively used.

I've used Boost.Mpl to generate variant-like classes.
For example, given a MPL type list such as this:
typedef boost::mpl::set<Foo, Bar, Baz> type_set;
I then use boost::mpl::fold to build a chain of classes derived from each others which each adds an std::unordered_set of one of the types in the type set. The end result is a class which contains an unordered_set<Foo>, an unordered_set<Bar> and an unordered_set<Baz>.
And because the class is specified in terms of a boost::mpl::set, I can iterate over these types to automatically generate other functions as well, such as an operator== which compares all of the unordered_sets.

The fact is, Boost.MPL, like Boost.Preprocessor, are really building blocks.
Most of the times, you probably use it through other libraries, as a number of Boost libraries are built upon those two.
For example:
Boost.Fusion (which crosses the gaps between compile-time and run-time realms)
Boost.MultiIndex (for an easier interface)
Boost.Unit (for dimensional analysis)
Boost.Variant may, I think, also depends on it
You may use it unknowningly already :)

I use a more enhanced dimensional analysis library called Boost.Units.
I've developed a compile-time reflection library and then used that library to build a generic class that provides runtime-reflection to any compile-time reflected type passed in. I've used that support to automatically generate UI components to edit the properties of such reflected types.
It's also paramount to the distribution of events within our application. For instance, when someone changes the units they wish the system to be in, I don't have to teach that system that new items have been added to given devices because the code uses MPL to analyze those types and just knows that something's been added and changes it.
I've just used metaprogramming techniques to wrap up the Qt signals into something that regains the type safety removed by their system and is able to connect with any functional entity.
But to tell the truth, you've almost certainly used practically applied metaprogramming techniques already when you've used standard algorithms like sort. A decent implementation of the sort algorithm uses a less evolved form of metaprogramming to analyze the iterators passed in and then uses tag-dispatching to initiate a sort algorithm capable of fully utilizing the features of those iterators.
Quite frankly, if you're not doing metaprogramming then you're not utilizing the power of C++ and you may as well be using something else.

When it comes to build matching engine, mostly for Exchange or DarkPool in trading area, we usually need to check if 2 orders could match or not (or we say could cross or not), there could be many aspects to check which we call as Rules, and here are the key requirements in term of organizing these rules:
It should be easy to add a new rule and get applied
It should be convenient to organize rules into different groups to apply the checks
Because the rule check are invoked quite frequently - well, of couse, that is the sole job of a matching engine, we want it as optimal as possible
This is a great fit to use boost mpl, which could use compile time sequence boost::mpl::vector to organize rules, and get them applied with boost::mpl::for_each.
The idea is best illustrated with an example:
It is straightforwrad to add a new rule by simply defining a new Rule class
It is convenient to group rules using boost::mpl::vector, and use it as a template parameter for canCross check
Because most of the setting up work are done in compile time, it is fast.
#include <iostream>
#include <vector>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
using namespace std;
struct Order {};
struct Rule1
{
const char* name() const { return "Rule1"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule1..." << endl; return true; }
};
struct Rule2
{
const char* name() const { return "Rule2"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule2..." << endl; return false;}
};
struct Rule3
{
const char* name() const { return "Rule3"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule3..." << endl; return false;}
};
struct Rule4
{
const char* name() const { return "Rule4"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule4..." << endl; return true;}
};
struct RuleApplicator
{
RuleApplicator(bool& success, std::vector<const char*>& failedRules, const Order& order1, const Order& order2):
_success(success),
_failedRules(failedRules),
_order1(order1),
_order2(order2)
{}
template <typename U> void operator() (U rule)
{
if(!rule.apply(_order1, _order2))
{
_success = false;
_failedRules.push_back(rule.name());
}
}
private:
bool& _success;
std::vector<const char*>& _failedRules;
const Order& _order1;
const Order& _order2;
};
template <class Rules>
bool canCross(const Order& a, const Order& b)
{
bool success = true;
std::vector<const char*> failedRules;
RuleApplicator applicator(success, failedRules, a, b);
boost::mpl::for_each<Rules>(applicator);
if (!success)
{
cout << "Can't cross due to rule check failure:";
for(const char* ruleName: failedRules)
{
cout << ruleName << " ";
}
cout << endl;
return false;
}
else
{
cout << "Can cross!" << endl;
return true;
}
}
int main(int argc, char** argv)
{
Order a, b;
canCross<boost::mpl::vector<Rule1, Rule4>>(a, b);
cout << endl;
canCross<boost::mpl::vector<Rule1, Rule2, Rule3, Rule4>>(a, b);
}
You will see output as:
Checking Rule1...
Checking Rule4...
Can cross!
Checking Rule1...
Checking Rule2...
Checking Rule3...
Checking Rule4...
Can't cross due to rule check failure:Rule2 Rule3

If your application has heavy logic in dealing with key-value pairs, you will need a ultra efficent way to get value from key, typical hashmap works well, but if possible keys are known upfront, optimzation could be done use boost::mpl, with an array, and a method to convert your key to array index at compile time, this is certainly more efficent.
Here is an example on handling fix message, which is a message contains various key-value pairs, it is used heavily in financial trading applications:
#include <iostream>
#include <array>
#include <string>
#include <unordered_set>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/size.hpp>
using namespace std;
using namespace boost;
struct TagEntity
{
bool isValid;
std::string value;
};
template<class CommonTags>
struct FixMsg
{
static constexpr uint32_t CommonTagsCount = mpl::size<CommonTags>::type::value;
template<int Tag>
constexpr uint32_t index()
{
constexpr auto idx = mpl::find<CommonTags, mpl::integral_c<int, Tag>>::type::pos::value; // this is the key step: convert tag to index in compile time
static_assert(idx < CommonTagsCount, "tag not found");
return idx;
}
template<int Tag>
TagEntity& getTagEntity()
{
return _commonTags[index<Tag>()];
}
std::array<TagEntity, CommonTagsCount> _commonTags; // or else use std::unordered_set, which is not as fast as this approach: absolute O(1) in runtime
};
int main(int argc, char** argv)
{
using MyCommonTags = mpl::vector_c<int,
11,
35,
10914,
10916>;
FixMsg<MyCommonTags> fixMsg;
auto& tagEntity = fixMsg.getTagEntity<11>();
tagEntity.isValid = true;
tagEntity.value = "Get tag entity in O(1)";
cout << tagEntity.value << endl;

I use boost::mpl (and boost::fusion) extensively in my stat_log library. This library allows the user to specify a hierarchy of statistic and logging tags and their associated behaviors, i.e. per-tag statistic types (histogram, counter, etc).
I rely heavily on metaprogramming to do the right thing with the user does:
stat_log::writeStat<IP_PKTS_RCVD>(450);
For example if the user defines the type trait:
template <>
struct stat_tag_to_type<IP_PKTS_RCVD>
{
using type = Accumulator<
stat_log::HistogramCount<
int,
1, //start bin
1500, //stop bin
10 //num_bits
>
>;
};
the "writeStat" call above will proxy (at compile time) to a histogram statistic. The powerful aspect of this design technique is the "writeStat" call site is not at all coupled with the particular statistic chosen.
I also use a wealth of MPL and boost::fusion to actually view the stats. Per your question, see the following files for the highest concentration of boost::mpl:
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/stat_log_impl.h
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/tag_commander.h
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/stat_log.h
especially the nifty template meta "function" in stat_log_impl.h:
//This template is used in conjunction with an MPL algorithm
// with the same semantics as mpl::find_if.
//BoolFunc is the "condition" metafunction.
//StatTagFunc is a metafunction that transforms the given
// stat_tag into something the algorithm requires.
// For example the "Identity" metafunction would work here.
//StatTagArgs is extra arguments to the BoolFunc
template <template<typename...> class BoolFunc,
template<typename...> class StatTagFunc,
class... StatTagArgs>
struct tag_node_query
{
template<typename TheTagNode>
struct apply
{
using stat_tag = typename TheTagNode::tag;
using type = std::integral_constant
<
bool,
BoolFunc<
typename StatTagFunc<stat_tag>::type,
StatTagArgs...
>::value
>;
};
};

To add to Matthieu's answer, it's also used quite extensively throughout both Boost.Python and Luabind.

Something funny I did:
https://github.com/edubois/static-factorial/blob/master/main.cpp
It uses a tiny part of boost::mpl to statically compute the value of factorial<8>()...
This can help to understand the main idea.

Related

standard interface of iterator::operator* that return more than T& and std::pair

Iterator of each datastructure has different type of return value of operator*() e.g. :-
Most array-like DataStructure<T> : return T&.
std::unordered_map<K,T> : return std::pair<const K, T>&.
const std::unordered_map<K,T> : return const std::pair<K, T>&.
What should be the datatype if my iterator::operator*() want to return something more complex (std::pair is not enough)?
Example
I have a custom 3D datastructure Map3D<T> that is like a map (int,int,int)->T.
To achieve the above requirement, I create a new class Bundle3D<T>.
template<class T>class Bundle3D {
//getInternalIndex1D()
//getCoordinate()
//getValue()
};
The Map3D<T>'s iterator::operator* would have signature like :-
Bundle3D<T> iterator::operator*(){ ... }
Its usage is like :-
Map3D<float> map;
for(auto& ele:map){ //"ele" has some special type named "Bundle"
int keyInternal1DIndex=ele.getInternalIndex1D();
Vector3Int& key=ele.getCoordinate();
float& value=ele.getValue();
}
It works good, but I think my code is not standardized.
In other words, Bundle3D<T>, getInternalIndex1D(), getCoordinate() and getValue() is blindly named by me.
In real case, I have created a lot of custom data-structures that generate such strange iterator.
Question
Is there any std::/standard type of return-value of iterator::operator*(), when T& and std::pair is not enough?
I have doubted about this for several months, but feel very reluctant to ask it.
If this question need improvement, please comment.
Edit
(clarify the word standardized - this part is my subjective notion.)
I feel that all types of standard collection in most language, e.g. :-
java.util.Collection/ArrayList in Java
std::unordered_map/vector in C++
Iterators of all of them have signatures of function getValue() or operator* that return either T or StandardPair<index,T> - no other types.
For many years, I am convinced that it is a rule or a strong convention/tradition that I really should obey.
There must be a reason.
However, I am not sure what it is, because I am probably very new to C++.
If I design my software to return something strange (e.g. Bundle3D<T> in the above example), I think I will get punished hard from the unconventional design. (e.g. not have .first field)
What you have right now is okay. I would just specify one thing that I think isn't very C++-ish and may in fact harm your standardization options in the future.
It's the getters. Obviously you have deep roots in Java, and the concept of public members is abhorred in Java programming, so much so that the concept of "beans" exists. I don't intend to knock on Java here, it's a nice language with its own nice idioms.
But this is C++, with it's own programming idioms. You obviously noticed the direct access to the contents of std::pair. It's like that for a reason. A pair is just two items packed together, that's the sum of its behavior. Getters would just ,well, get in the way. :)
There's no need for them, because we aren't dealing with an "abstraction" of two items bundled together, but instead we really do have a concrete, honest to god, bundle1.
Obviously we can have bundles of more than two items. That's why we have std::tuple. Now while it's true that all access to a tuple is through a non-member function called get, that's simply because there is no way to give names to members of an arbitrarily sized bundle. get still returns a reference to the element, so you retain direct access into the bundle.
This long winded exposition is important, because an upcoming C++1z feature, called "Structured Bindings", relies on the standard behavior of tuples and pairs, as well as how C++ programmers see aggregates. Under this feature, an iteration over a map, will look like this:
#include <map>
#include <iostream>
std::map<char const*, int> foo()
{
return {
{ "foo", 3 },
{ "bar", 7 },
{ "baz", 1 },
};
}
int main() {
for (auto [key, val] : foo()) {
std:: cout << "( " << key << ", " << val << " )\n";
}
return 0;
}
Live example
And the same extends to any user defined bundle of data. Your own return value type in the post can be bound similarly, if the members are public:
struct Vector3Int {};
template<class T>
struct Bundle3D {
int internal_index_id;
Vector3Int const &coord;
T &value;
};
int main() {
Vector3Int vec;
float val;
Bundle3D<float> bundle{ 1, vec, val };
auto[ idx_id, coord, value] = bundle;
// coord = {}; // compile error since coord gets the cv qualifer
}
Live example
So my suggestion is, leave the getters to your Java code, and use aggregates as bundles of data for C++.
1 An aggregate, to be more formal.
I'm going to assume that your Map3D is a spacial co-ordinate to value container.
I would return a std::pair<const Vector3Int, T>&, and not bother with getInternalIndex1D as part of the return. That can be left as a function Vector3Int -> int.
Have a look at UnorderedAssociativeContainer for the sorts of members that would be useful to define
e.g.
template <typename T>
class Map3D
{
using key_type = Vector3Int;
using mapped_type = T;
using value_type = Bundle3D<T>; // Key, Value, Internal1DIndex
using reference = Bundle3D<T> &;
using pointer = Bundle3D<T> *;
using hasher = /*Function object that calculates Internal1DIndex*/
using key_equal = std::equal<Vector3Int>
... iterators, const_* definitions, etc
}

What is the "correct OOP" way to deal with a storage pool of items of mixed types?

This was inspired by a comment to my other question here:
How do you "not repeat yourself" when giving a class an accessible "name" in C++?
nvoight: "RTTI is bad because it's a hint you are not doing good OOP. Doing your own homebrew RTTI does not make it better OOP, it just means you are reinventing the wheel on top of bad OOP."
So what is the "good OOP" solution here? The problem is this. The program is in C++, so there are also C++ specific details mentioned below. I have a "component" class (actually, a struct), which is subclassed into a number of different derived classes containing different kinds of component data. It's part of an "entity component system" design for a game. I'm wondering about the storage of the components. In particular, the current storage system has:
a "component manager" which stores an array, actually a hash map, of a single type of component. The hash map allows for lookup of a component by the entity ID of the entity it belongs to. This component manager is a template which inherits from a base, and the template parameter is the type of component to manage.
a full storage pack which is a collection of these component managers, implemented as an array of pointers to the component manager base class. This has methods to insert and extract an entity (on insertion, the components are taken out and put into the managers, on removal, they are extracted and collected into a new entity object), as well as ones to add new component managers, so if we want to add a new component type to the game, all we have to do is put another command to insert a component manager for it.
It's the full storage pack that prompted this. In particular, it offers no way of accessing a particular type of component. All the components are stored as base class pointers with no type information. What I thought of was using some kind of RTTI and storing the component managers in a map which maps type names and thus allows for lookup and then the proper downcasting of the base class pointer to the appropriate derived class (the user would call a template member on the entity storage pool to do this).
But if this RTTI means bad OOP, what would be the correct way to design this system so no RTTI is required?
Disclaimer/resources: my BCS thesis was about the design and implementation of a C++14 library for compile-time Entity-Component-System pattern generation. You can find the library here on GitHub.
This answer is meant to give you a broad overview of some techniques/ideas you can apply to implement the Entity-Component-System pattern depending on whether or not component/system types are known at compile-time.
If you want to see implementation details, I suggest you to check out my library (linked above) for an entirely compile-time based approach. diana is a very nice C library that can give you an idea of a run-time based approach.
You have several approaches, depending on the scope/scale of your project and on the nature of your entities/components/systems.
All component types and system types are known at compile-time.
This is the case analyzed in my BCS thesis - what you can do is use advanced metaprogramming techniques (e.g. using Boost.Hana) to put all component types and system types in compile-time lists and create data structures that link everything together at compile time. Pseudocode example:
namespace c
{
struct position { vec2f _v };
struct velocity { vec2f _v };
struct acceleration { vec2f _v };
struct render { sprite _s; };
}
constexpr auto component_types = type_list
{
component_type<c::position>,
component_type<c::velocity>,
component_type<c::acceleration>,
component_type<c::render>
};
After defining your components, you can define your systems and tell them "what components to use":
namespace s
{
struct movement
{
template <typename TData>
void process(TData& data, float ft)
{
data.for_entities([&](auto eid)
{
auto& p = data.get(eid, component_type<c::position>)._v;
auto& v = data.get(eid, component_type<c::velocity>)._v;
auto& a = data.get(eid, component_type<c::acceleration>)._v;
v += a * ft;
p += v * ft;
});
}
};
struct render
{
template <typename TData>
void process(TData& data)
{
data.for_entities([&](auto eid)
{
auto& p = data.get(eid, component_type<c::position>)._v;
auto& s = data.get(eid, component_type<c::render>)._s;
s.set_position(p);
some_context::draw(s);
});
}
};
}
constexpr auto system_types = type_list
{
system_type<s::movement,
uses
(
component_type<c::position>,
component_type<c::velocity>,
component_type<c::acceleration>
)>,
system_type<s::render,
uses
(
component_type<c::render>
)>
};
All that's left is using some sort of context object and lambda overloading to visit the systems and call their processing methods:
ctx.visit_systems(
[ft](auto& data, s::movement& s)
{
s.process(data, ft);
},
[](auto& data, s::render& s)
{
s.process(data);
});
You can use all the compile-time knowledge to generate appropriate data structures for components and systems inside the context object.
This is the approach I used in my thesis and library - I talked about it at C++Now 2016: "Implementation of a multithreaded compile-time ECS in C++14".
All component types and systems types are known at run-time.
This is a completely different situation - you need to use some sort of type-erasure technique to dynamically deal with components and systems. A suitable solution is using a scripting language such as LUA to deal with system logic and/or component structure (a more efficient simple component definition language can also be handwritten, so that it maps one-to-one to C++ types or to your engine's types).
You need some sort of context object where you can register component types and system types at run-time. I suggest either using unique incrementing IDs or some sort of UUIDs to identify component/system types. After mapping system logic and component structures to IDs, you can pass those around in your ECS implementation to retrieve data and process entities. You can store component data in generic resizable buffers (or associative maps, for big containers) that can be modified at run-time thanks to component structure knowledge - here's an example of what I mean:
auto c_position_id = ctx.register_component_type("./c_position.txt");
// ...
auto context::register_component_type(const std::string& path)
{
auto& storage = this->component_storage.create_buffer();
auto file_contents = get_contents_from_path(path);
for_parsed_lines_in(file_contents, [&](auto line)
{
if(line.type == "int")
{
storage.append_data_definition(sizeof(int));
}
else if(line.type == "float")
{
storage.append_data_definition(sizeof(float));
}
});
return next_unique_component_type_id++;
}
Some component types and system types are known at compile-time, others are known at run-time.
Use approach (1), and create some sort of "bridge" component and system types that implements any type-erasure technique in order to access component structure or system logic at run-time. An std::map<runtime_system_id, std::function<...>> can work for run-time system logic processing. An std::unique_ptr<runtime_component_data> or an std::aligned_storage_t<some_reasonable_size> can work for run-time component structure.
To answer your question:
But if this RTTI means bad OOP, what would be the correct way to design this system so no RTTI is required?
You need a way of mapping types to values that you can use at run-time: RTTI is an appropriate way of doing that.
If you do not want to use RTTI and you still want to use polymorphic inheritance to define your component types, you need to implement a way to retrieve some sort of run-time type ID from a derived component type. Here's a primitive way of doing that:
namespace impl
{
auto get_next_type_id()
{
static std::size_t next_type_id{0};
return next_type_id++;
}
template <typename T>
struct type_id_storage
{
static const std::size_t id;
};
template <typename T>
const std::size_t type_id_storage<T>::id{get_next_type_id()};
}
template <typename T>
auto get_type_id()
{
return impl::type_id_storage<T>::id;
}
Explanation: get_next_type_id is a non-static function (shared between translation units) that stores a static incremental counter of type IDs. To retrieve the unique type ID that matches a specific component type you can call:
auto position_id = get_type_id<position_component>();
The get_type_id "public" function will retrieve the unique ID from the corresponding instantiation of impl::type_id_storage, that calls get_next_type_id() on construction, which in turn returns its current next_type_id counter value and increments it for the next type.
Particular care for this kind of approach needs to be taken to make sure it behaves correctly over multiple translation units and to avoid race conditions (in case your ECS is multithreaded). (More info here.)
Now, to solve your issue:
It's the full storage pack that prompted this. In particular, it offers no way of accessing a particular type of component.
// Executes `f` on every component of type `T`.
template <typename T, typename TF>
void storage_pack::for_components(TF&& f)
{
auto& data = this->_component_map[get_type_id<T>()];
for(component_base* cb : data)
{
f(static_cast<T&>(*cb));
}
}
You can see this pattern in use in my old and abandoned SSVEntitySystem library. You can see an RTTI-based approach in my old and outdated “Implementation of a component-based entity system in modern C++” CppCon 2015 talk.
Despite the good and long answer by #VittorioRomeo, I'd like to show another possible approach to the problem.
Basic concepts involved here are type erasure and double dispatching.
The one below is a minimal, working example:
#include <map>
#include <vector>
#include <cstddef>
#include <iostream>
#include <memory>
struct base_component {
static std::size_t next() noexcept {
static std::size_t v = 0;
return v++;
}
};
template<typename D>
struct component: base_component {
static std::size_t type() noexcept {
static const std::size_t t = base_component::next();
return t;
}
};
struct component_x: component<component_x> { };
struct component_y: component<component_y> { };
struct systems {
void elaborate(std::size_t id, component_x &) { std::cout << id << ": x" << std::endl; }
void elaborate(std::size_t id, component_y &) { std::cout << id << ": y" << std::endl; }
};
template<typename C>
struct component_manager {
std::map<std::size_t, C> id_component;
};
struct pack {
struct base_handler {
virtual void accept(systems *) = 0;
};
template<typename C>
struct handler: base_handler {
void accept(systems *s) {
for(auto &&el: manager.id_component) s->elaborate(el.first, el.second);
}
component_manager<C> manager;
};
template<typename C>
void add(std::size_t id) {
if(handlers.find(C::type()) == handlers.cend()) {
handlers[C::type()] = std::make_unique<handler<C>>();
}
handler<C> &h = static_cast<handler<C>&>(*handlers[C::type()].get());
h.manager.id_component[id] = C{};
}
template<typename C>
void walk(systems *s) {
if(handlers.find(C::type()) != handlers.cend()) {
handlers[C::type()]->accept(s);
}
}
private:
std::map<std::size_t, std::unique_ptr<base_handler>> handlers;
};
int main() {
pack coll;
coll.add<component_x>(1);
coll.add<component_y>(1);
coll.add<component_x>(2);
systems sys;
coll.walk<component_x>(&sys);
coll.walk<component_y>(&sys);
}
I tried to be true to the few points mentioned by the OP, so as to provide a solution that fits the real problem.
Let me know with a comment if the example is clear enough for itself or if a few more details are required to fully explain how and why it works actually.
If I understand correctly, you want a collection, such as a map, where the values are of different type, and you want to know what type is each value (so you can downcast it).
Now, a "good OOP" is a design which you don't need to downcast. You just call the mothods (which are common to the base class and the deriveratives) and the derived class performs a different operation than its parent for the same method.
If this is not the case, for example, where you need to use some other data from the child and thus you want to downcast, it means, in most cases, you didn't work hard enough on the design. I don't say it's always possible, but you need to design it in such a way the polymorphism is your only tool. That's a "good OOP".
Anyway, if you really need to downcast, you don't have to use RTTI. You can use a common field (string) in the base class, that marks the class type.

Best practice with argument dependent name lookup

today i face a problem that hurts my peace of mind. I have resumed my problem in a very smart and meaningfull example where the expected result is not met although no error is generated.
#include <iostream>
namespace MATH {
template <std::size_t M, std::size_t N, class T>
class Matrix
{
};
void invert(Matrix<2, 2, double>& m)
{
std::cout << "DIM 2 : MATH version (use of the determinant)" << std::endl;
}
void invert(Matrix<3, 3, double>& m)
{
std::cout << "DIM 3 : MATH version (use of the determinant)" << std::endl;
}
}
namespace GEOM {
template <std::size_t N>
using Matrix = MATH::Matrix<N, N, double>;// orthonormal set of vectors
template <std::size_t N>
void invert(Matrix<N>& m)
{
std::cout << "DIM " << N << " : GEOM version (use of the transpose)" << std::endl;
}
void geom_foo_purpose(Matrix<3>& m)
{
invert(m);
}
}
int main(int argc, char **argv)
{
GEOM::Matrix<3> m;
GEOM::geom_foo_purpose(m);
return 0;
}
output : std::cout << "DIM 3 : MATH version (use of the determinant)" << std::endl;
In geom_foo_purpose definition, the call to invert results in an unqualified id because a template deduction is requested. So, the ADL is able to say : ok, let's look at the MATH namespace. The fact that allows MATH::invert to be prefered to the GEOM::invert version because the non template version has priority is inadmissible in this case i think.
For example, i want to develop the GEOM content first, by defining the Matrix class as a GEOM type. GEOM::invert is called. No problem.
One day, i want to generalize my Matrix class in another namespace MATH and i could think : ok, i keep the same methods and i don't break the code. Just put a using MATH::Matrix... And i become unable to understand where is the performance overhead nor why some sensitive measures change.
So i actually think about three solutions :
verify each namespaces when i add a function or when i change a using
specify the namespace for each call
rely on ambiguous call compiler errors, when detected
Is there a decent way to overcome this ?
The problem is that your GEOM::Matrix is only a synonym of MATH::Matrix, and not a new type in GEOM. This is the intended effect of a using statement, and therefore the argument dependent name lookup finds the MATH::invert() as the best match.
If you want to fix this, define a real GEOM::Matrix this way:
template <std::size_t N>
class Matrix : public MATH::Matrix<N, N, double> {};// orthonormal set of vectors
Here an online demo.
Edit:
There's a fundamental design issue that you have to decide on:
Either you want to have distinct (yet somewhat interchangeable) Matrix types and benefit from ADL. In this case you manage two types and can have of course to manage some conversions (from GEOM to MATH).
Or you want to have one single Matrix type (defined in one namespace) with specialisation for some parameters (in the same namespace, i.e. the transposition inversion would migrate to MATH).
Boh have their advantages and inconvenience. The choice is yours. Personally I'd prefer the second option: all the matrix specific operations would then better isolated. And as you say, a matrix is a matrix. But apparently, you've choosen the second option, and my answer tries to provide you some solutions for that.
General advice
It is best practice to keep classes and functions that are designed to work together in one namespace to enable ADL. (See Item #57 in C++ Coding Standards: Keep a type and its nonmember function interface in the same namespace.) Sometimes it is recommended to keep unrelated classes and functions in separate namespaces. (See Item #58 in the same book.) I find this too restrictive, because it creates a huge namespace jungle very quickly.
Common practice
It is more common practice to put all stuff that belongs logically to one library into one namespace. It's the libraries responsibility to avoid internal name clashes. Users of the library should usually not add new stuff to a libraries namespace. That's pretty much how the standard library, boost, OpenCV and a host of other libraries work. That's what I recommend. Don't try to overseparate. It just hurts your head and is not necessary.
Namespace usage
These common libraries use nested namespaces for some purposes, like boost::detail for implementation details, that should not be of interest to the user of the library. Other examples where more namespaces are necessary are
inline namespaces for versioning and
namespaces to select a set of user-defined literals and
possibly some others.
EDIT:
Advice for your situation
If I understand correctly, your GEOM::Matrix is supposed to be an orthogonal matrix. (I just noticed that very late and would suggest a clearer name for it.) That should be a different type, this type has to ensure the internal invariant of being orthogonal. Using using or typedef just does aliasing and there's no way for you to guarantee, that the invariant if broken through some MATH::Matrix functions. Therefore, I would suggest composition as the means to solve the problem:
namespace GEOM
{
template <std::size_t N, typename T>
class OrthogonalMatrix
{
private:
MATH::Matrix<N,N,T> mat;
public:
// Enable use of const interface of MATH::Matrix<N,N,T>.
operator const MATH::Matrix<N,N,T> &() const { return mat; }
// ... here goes the implementation ensuring
// orthogonality at all times.
};
} // end of namespace GEOM
An alternative would be private inheritance, which enables you to make MATH::Matrix methods public selectively with the keyword using like this:
namespace GEOM
{
template <std::size_t N, typename T>
class OrthogonalMatrix : private MATH::Matrix<N,N,T>;
{
public:
// Make `MATH::Matrix<N,N,T>::transposeInPlace` publicly accessible
using MATH::Matrix<N,N,T>::transposeInPlace;
// Enable use of const interface of MATH::Matrix<N,N,T>.
operator const MATH::Matrix<N,N,T> &() const { return *this; }
// ... here goes the implementation ensuring
// orthogonality at all times.
};
} // end of namespace GEOM
You should not do that with the constructor or entry access functions, since they would enable the user of the class to break invariants which can easily lead to a lot of confusion. Also public inheritance plus using in the private section would be wrong, because the user of the class would still be able to break invariants by converting to MATH::Matrix<N,N,T> & and messing up the matrix then.

Calling the appropriate function based on an enumeration, but using templates

I have this wrapper function that is supposed to call the appropriate function on a large dataset based on the type of data it contains, like this:
void WrapperFunc( int iRealDataType, int iUseAsDataType )
{
// now call the right function based on both arguments
switch ( iRealDataType )
{
case FancyType1:
switch ( iUseAsDataType )
{
case CoolType1: DataAnalysisFunc_Fancy1_Cool1(); break;
// etc.
}
// etc.
}
}
So far, this was solved by having two nested switch statements and then calling one of the many many specialized functions for each existing combination of Real and UseAs data type. However as the number of defined types grows it is a nightmare to maintan the code base. So I decided to finally use templates. I mostly avoid them if I can, but this time they suit the problem well.
So now instead of DataAnalysisFunc_Fancy1_Cool1 i would like to call DataAnalysisFunc<FancyType1,CoolType1> ang get rid of the hundreds of lines of switch statements, BUT i cannot use it like this, since FancyType1 is an enum, not the type (which is Fancy1 for example).
Just to clarify - I know this sounds like a stupid artificial example, but I tried to simplify the problem as much as possible to get to the core of it, instead of explaining the ton of details that would go into a much more concrete example.
EDIT: my data analysis functions are in reality CUDA kernels - this will probably rule out some possible solutions. Sorry for that.
Templates sound like the wrong solution. What you want is a lookup table.
typedef void (*DataAnalysisFunc)();
const DataAnalysisFunc DataAnalysisFunctions[NumFancyTypes][NumCoolTypes] = {
/*Fancy1*/ {
/*Cool1*/ &DataAnalysisFunc_Fancy1_Cool1,
/*Cool2*/ &DataAnalysisFunc_Fancy1_Cool2 }
/*Fancy2*/ {
/*Cool1*/ &DataAnalysisFunc_ImpossibleCombination, // can't happen, throw or something
/*Cool2*/ &DataAnalysisFunc_Fancy2_Cool2 }
};
void WrapperFunc(int realDataType, int useAsDataType) {
assert(realDataType >= 0 && realDataType < NumFancyTypes);
assert(useAsDataType >= 0 && useAsDataType < NumCoolTypes);
(*DataAnalysisFunctions[realDataType][useAsDataType])();
}
Now, if those DataAnalysisFuncs share a lot of code, templates might help you there, but not for dynamic dispatch.
BUT i cannot use it like this, since FancyType1 is an enum, not the
type (which is Fancy1 for example)
You can convert enum to type, just use one of metaprogramming basic tools:
Int2Type, it is used to replace run-time branches of if statements on the compile time dispatches.
It looks like:
template <int Number>
struct Int2Type
{
enum {value};
};
Int2Type - is treated as a type, using it and function overloading - you can replace if statements.
UPDATE:
I added some example here, to make my answer more clear
1. Int2Type
// usage allows to implement dispatch in a compile time instead of branching statements in a run-time
template <int Val>
struct Int2Type
{
static const int val_= Val;
};
template <typename ItBegin, typename ItEnd>
void doSort(ItBegin it0, ItEnd it1, Int2Type<1>)
{
using namespace std;
// sort
cout << "Standart sorting algorithm was used. For iterators" << endl;
}
template <typename ItBegin, typename ItEnd>
void doSort(ItBegin it0, ItEnd it1, Int2Type<2>)
{
using namespace std;
// sort
cout << "Fast sorting algorithm was used. For pointers" << endl;
}
// based on the 3-rd dummy type parameter call will be dispatched to needed function
int arr[3];
MainTools::doSort(arr, arr + sizeof(arr) / sizeof(arr[0]), MainTools::Int2Type<1>());
vector<int> v(3);
MainTools::doSort(v.begin(), v.end(), MainTools::Int2Type<2>());
You're looking for type dispatching. I find this easiest to do with Boost.MPL.
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
struct DispatchChecker
{
int iRealDataType, iUseAsDataType;
template <class T>
void operator()(T) const
{
static const int iCurrentReal = boost::mpl::at_c<T, 0>::type::value;
static const int iCurrentUseAs = boost::mpl::at_c<T, 1>::type::value;
if(iRealDataType == iCurrentReal &&
iUseAsDataType == iCurrentUseAs)
DataAnalysisFunc<iCurrentReal,iCurrentUseAs>();
}
};
typedef /*mpl sequence of all valid types*/ valid_types;
boost::mpl::for_each<valid_types>(DispatchChecker{iRealDataType,iUseAsDataType});
boost::mpl::for_each accepts a compile time sequence and instantiates and runs a functor on each element of the sequence. In this case the functor checks that the compile parameters match the runtime parameters and calls the appropriate DataAnalysisFunc when they match.
As for how to get the valid_types, the easiest way is to just write out each valid pair in a sequence like this:
typedef boost::mpl::vector<
boost::mpl::vector_c<int, 0, 0>,
boost::mpl::vector_c<int, 2, 0>,
boost::mpl::vector_c<int, 1, 1>,
boost::mpl::vector_c<int, 0, 2>,
boost::mpl::vector_c<int, 1, 2>
> valid_types;
Note:
As Sebastian Redl points out, using templates is probably only worthwhile if the DataAnalasysFuncs share a lot code between them, otherwise a runtime dispatch is probably a much better solution.

How to read through types of a struct in C/C++

I am trying to find the "types" of any given variables in different structs and be able to read them. (keep in mind this is psuedo code)
For Example:
#include "stream.h" //a custom stream reader class I made
typedef unsigned char BYTE;
/***** SERIES OF DIFFERENT STRUCTS ******/
struct asset
{
char *name;
int size;
BYTE *data;
};
struct asset2
{
char *lang;
char *entry;
};
/*****************************************/
void readAsset( Enumerable<struct> &istruct)
{
foreach( object o in istruct )
{
switch( o )
{
case int:
&o = _stream->ReadInt32();
break;
case char:
&o = _stream->ReadChar();
break;
case *:
&o = _stream->ReadInt32();
break;
default: break;
}
}
}
I want it to be able to do the following:
asset a1;
asset2 a2;
readAsset( a1 );
readAsset( a2 );
and pass all the info from the file to a1 and a2.
I was wondering if there was a way in C/C++ to get the type of the data from any object in the struct then read based on that? is it possible with complex enums? Sorry for the bad code but I wanted it to be easier to understand what I'm trying to do.
Additional Info:
_stream is a pointer to a Stream class I made similar to Stream Reader in .Net It reads data from a file and advances it's position based on how big of data it was read.
I'll be happy to re-phrase if you don't understand what I'm asking.
There is no way to iterate through the members of a structure without listing them all out.
You can iterate through something like a structure at compile time using ::std::tuple in C++11.
You also can't really switch on type in that fashion. You can do it, but the way you do it is to have several functions with the same name that each take a different parameter type. Something like:
void doRead(StreamType &stream, int &data)
{
data = stream.readInt32();
}
void doRead(StreamType &stream, char &data)
{
data = stream.readChar();
}
// etc...
Then you just call doRead with your structure member and poof the compiler magically picks the right one based on the type.
In C++, the way to solve the problem you're solving here is a serialization library. If you have control of both the format written and the format read, you can use something like protobuf or boost::serialization to do this relatively easily without having to write a lot of your own code.
Additionally, a couple of issues with your code. Do not use a leading _ character in identifiers. Identifiers with a leading _ are reserved for use by the compiler or standard library implementation. Many compilers have special keywords that are compiler specific language extensions that start with an _ character. Using identifiers with a leading _ character may result in your code mysteriously failing to compile with all kinds of strange inscrutable errors in some environments.
You can get something like a struct that is enumerable at compile time. But it's ugly:
#include <tuple>
#include <string>
#include <vector>
#include <type_traits>
class asset : public ::std::tuple< ::std::string, ::std::vector<BYTE> >
{
public:
::std::string &name() { return ::std::get<0>(*this); }
const ::std::string &name() const { return ::std::get<0>(*this); }
::std::vector<BYTE> &data() { return ::std::get<1>(*this); }
const ::std::vector<BYTE> &data() const { return ::std::get<1>(*this); }
};
void writeToStream(Stream *out, const ::std::string &field)
{
out->writeString(field);
}
void writeToStream(Stream *out, const ::std::vector<BYTE> &field)
{
out->writeInt(field.size());
out->writeRaw(field.data(), field.size());
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum < sizeof...(T)), void >::type
writeToStream_n(Stream *out, const::std::tuple<T...> &field)
{
writeToStream(out, ::std::get<fnum>(field));
writeToStream_n<fnum+1, T...>(out, field);
}
template <unsigned int fnum, typename... T>
typename ::std::enable_if< (fnum >= sizeof...(T)) >::type
writeToStream_n(Stream *, const::std::tuple<T...> &)
{
}
template <typename... Tp>
void writeToStream(Stream *out, const ::std::tuple<Tp...> &composite)
{
writeToStream_n<0, Tp...>(out, composite);
}
void foo(Stream *out, const asset &a)
{
writeToStream(out, a);
}
Notice that there is no explicit writeToStream for the asset type. The compiler will write it at runtime by unpacking the ::std::tuple it's derived from and writing out each individual field.
Also, if you have bare pointers, you're writing poor C++. Please write idiomatic, good C++ if you're going to write C++. This whole thing you want to do with runtime reflection is just not the way to do things.
That's the reason I converted your char *name to a ::std::string and your size delimited BYTE array represented by your size and data fields into a ::std::vector. Using those types is the idiomatically correct way to write C++. Using bare pointers the way you were is not. Additionally, having two fields that have strongly related values (the data and size) fields that have no behavior or any other indication that they're associated would make it hard even for a compiler that does introspection at runtime to figure out the right thing to do. It can't know how big the BYTE array being pointed to by data is, and it can't know about your decision to encode this in size.
What you're asking for is something called Reflection - which is:
the ability of a computer program to examine
and modify the structure and behavior (specifically the values,
meta-data, properties and functions) of an object at runtime.
C++ doesn't have that "natively".
What I mean is - there have been some attempts at introducing some aspects of it - with varied degrees of success - which have produced some aspects of Reflection, but not "full" Reflection itself as you will get in a language like Ruby or so.
However, if you are feeling adventurous, you can try a Reflection library called Reflectabit:
To see if it might be worthwhile (which it might be considering your code), it is referenced here - which has quite a bit of examples on how to use the API:
http://www.altdevblogaday.com/2011/09/25/reflection-in-c-part-1-introduction/
Good luck!
The usual pattern in C++ is not to try and figure out what the members of the type are, but rather provide an operator, implemented by the implementor of the type, that is able to serialize/deserialize to disk.
You can take a look at, for example, the boost::serialize library. The usage is not too complex, you need to provide a function that lists your members in some order and then the library will take it from there and implement serialization to different formats.