Using gcc or clang latest, boost 1.68 (or 1.69),
Compiling boost.spirit.karma example customize_embedded_container.cpp fails, unless replacing type with value_type in line 26.
The other useful example, customize_use_as_container.cpp also fails, asking for value_type etc. in indirect_iterator,
" no named type 'value_type' in 'std::iterator_traits' "
For the reference, the example : https://www.boost.org/doc/libs/1_69_0/libs/spirit/example/karma/customize_use_as_container.cpp
Any that have a clue or a working example for container-specialisation that is compiling in boost.spirit.karma ?
Given my case, a skeleton for the solution, or rather a workaround just playing with the parts that really works easy in boost.spirit:
namespace X {
struct p { double t,v;};// point, time, value
struct ts { // simplified time-series representation, time-axis computed
bool s;
double t0,dt;size_t n;// ti = t0 + dt*i
std::vector<double> v;// v.size()===n
p point(size_t i ) const { return p{t0+dt*i,v[i]};}
};
//--would like to output grammar like {pfx:(true|false),data:[[t,v]..]}
//--; first construct a container class out of ts, using boost iterator_facade
//--; to get away with few lines.(simplified..)
struct ts_c {
using value_type=p;// iterate over (t,v), t is computed, v is plain vector
ts * c;
struct iterator:public::boost::iterator_facade<iterator,p,boost::random_access_traversal..> { //..
iterator(ts*c,size_t pos=0u):c{c},pos{pos} {}
//.. plain vanilla impl. goes here according to boost::iterator_facade.
private:
ts* c;
size_t pos;
};
using const_iterator=iterator;
iterator begin() const;//.. etc. impl. of need it stuff.
};
}
// use FUSION to adapt the ts-type, let last tuple member return the
// tuple members:
// 0 true if n>0, otherwise false
// 1 true if ts.s is true
// 2 returns a vanilla iterable container, ts_c exposing type p
BOOST_FUSION_ADAPT_ADT(
X::ts,
(bool,bool, obj.n>0,/**/)
(bool,bool,obj.s,/**/)
(X::ts_c,X::ts_c, X::ts_c(&obj),/**/)
)
//-- then combining the boost spirit complex example to emit the point class p
namespace X {
namespace ka=boost::spirit::karma;
/** generate a point like [123.0, 3.14], or [123.0,null] if !isfinite.
* using the complex example pattern given in boost::spirit,
*/
template<class OutputIterator>
struct point_generator:ka::grammar<OutputIterator,p()> {
point_generator():point_generator::base_type(pg) {
using ka::true_;
using ka::bool_;
using ka::omit;
pg =
&true_ <<( '[' << double_<< ',' << double_ << ']')
|
omit[bool_]<< ( '[' << double_<< ',' << "null" << ']')
;
}
ka::rule<OutputIterator,p()> pg;
};
/** #brief a ts generator
*
* outputs:
* {pfx:(true|false),data:[[t,v],..]}
* or if empty
* {pfx:null,data:null}
*/
template<class OutputIterator>
struct ts_generator:ka::grammar<OutputIterator,ts()> {
ts_generator():ts_generator::base_type(tsg) {
using ka::true_;
using ka::bool_;
using ka::omit;
tsg =
&true_ <<"{pfx:"<<bool_<<",data:"<<( '[' << pt_ % ',' << ']')<<'}'
|
omit[bool_]<< "{pfx:null: data:null}"
;
}
ka::rule<OutputIterator,ts()> tsg;
point_generator<OutputIterator> pt_;
};
}
Related
From this SO topic (and this blog post), I know how to access Nth type in a template parameter pack. For instance, one of the answers to the abovementioned SO question suggests this:
template<int N, typename... Ts> using NthTypeOf = typename std::tuple_element<N, std::tuple<Ts...>>::type;
using ThirdType = NthTypeOf<2, Ts...>;
However, these methods work only in compile-time. Trying to do something such as:
int argumentNumber = 2;
using ItsType = NthTypeOf<argumentNumber, Arguments...>;
would result in compile error:
Error : non-type template argument is not a constant expression
Is there a way to access Nth type at runtime?
Here's my use case:
My program reads a text file, which is basically an array of numbers. Each number i refers to the i-th type of a template parameter pack that my class is templated based on. Based on that type, I want to declare a variable of that type and do something differently with it. For example, if it's a string, I want to declare a string and do string matching, and if it's an integer, I would like to compute the square root of a number.
C++ is a statically typed language. As such the type of all variables needs to be known at compile time (and cannot vary). You want a type that depends on a runtime value. Luckily C++ also features dynamic typing of objects.
Warning: all code in this answer serves only for demonstration of the basic concept/idea. It's missing any kind of error handling, sane interfaces (constructors...), exception safety, ... . So don't use for production, consider using the implementations available from boost.
To use this feature you need what's called a polymorphic base class: a class with (at least) one virtual member function from which you derive further classes.
struct value_base {
// you want to be able to make copies
virtual std::unique_ptr<value_base> copy_me() const = 0;
virtual ~value_base () {}
};
template<typename Value_Type>
struct value_of : value_base {
Value_Type value;
std::unique_ptr<value_base> copy_me() const {
return new value_of {value};
}
};
You can then have a variable with static type of pointer or reference to that base class, which can point to/reference objects from both the base class as well as from any of those derived classes. If you have a clearly defined interface, then encode that as virtual member functions (think of Shape and area (), name (), ... functions) and make calls through that base class pointer/reference (as shown in the other answer). Otherwise use a (hidden) dynamic cast to obtain a pointer/reference with static type of the dynamic type:
struct any {
std:: unique_ptr<value_base> value_container;
// Add constructor
any(any const & a)
: value_container (a.value_container->copy_me ())
{}
// Move constructor
template<typename T>
T & get() {
value_of<T> * typed_container
= dynamic_cast<value_of<T> *>(value_container.get();)
if (typed_container == nullptr) {
// Stores another type, handle failure
}
return typed_container->value;
}
// T const & get() const;
// with same content as above
};
template<typename T, typename... Args>
any make_any (Args... && args) {
// Raw new, not good, add proper exception handling like make_unique (C++14?)
return {new T(std:: forward<Args>(args)...)};
}
Since object construction is done at runtime the actual type of the pointed to/referenced object may depend on runtime values:
template<typename T>
any read_and_construct (std:: istream & in) {
T value;
// Add error handling please
in >> value;
return make_any<T>(std:: move (value));
}
// ...
// missing: way of error handling
std::map<int, std:: function<any(std:: istream &)>> construction_map;
construction_map.insert(std::make_pair(1, read_and_construct<double>));
// and more
int integer_encoded_type;
// error handling please
cin >> integer_encoded_type;
// error handling please
any value = construction_map [integer_encoded_type] (cin);
As you may have noticed above code uses also a clearly defined interface for construction. If you don't intend to do lots of different things with the returned any objects, potentially storing them in various data structures over great parts of the time your program is running, then using an any type is most likely overkill and you should just put the type dependent code into those construction functions, too.
A serious drawback of such an any class is its generality: it's possible to store just about any type within it. This means that the (maximum) size of the (actually) stored object is not known during compilation, making use of storage with automatic duration (the "stack") impossible (in standard C++). This may lead to expensive usage of dynamic memory (the "heap"), which is considerably slower than automatic memory. This issue will surface whenever many copies of any objects have to be made, but is probably irrelevant (except for cache locality) if you just keep a collection of them around.
Thus, if you know at compile time the set of types which you must be able to store, then you can (at compile time) compute the maximum size needed, use a static array of that size and construct your objects inside that array (since C++11 you can achieve the same with a (recursive template) union, too):
constexpr size_t max_two (size_t a, size_t b) {
return (a > b) ? a : b;
}
template<size_t size, size_t... sizes>
constexpr size_t max_of() {
return max_two (size, max_of<sizes>());
}
template<typename... Types>
struct variant {
alignas(value_of<Types>...) char buffer[max_of<sizeof (value_of<Types>)...>()];
value_base * active;
// Construct an empty variant
variant () : active (nullptr)
{}
// Copy and move constructor still missing!
~variant() {
if (active) {
active->~value_base ();
}
}
template<typename T, typename... Args>
void emplace (Args... && args) {
if (active) {
active->~value_base ();
}
active = new (buffer) T(std:: forward<Args>(args)...);
}
};
C++ is a statically-typed language, which means that the types of variables cannot be decided or changed at runtime.
Because your array of numbers are input at runtime, it's impossible for you to use the NthTypeOf metafunction in the manner you describe, because NthTypeOf can only depend on a compile-time index.
In your use case, not only are the variables of different type, but the behavior is also different based on user input.
If you want different behavior based on a value determined at runtime, I suggest either a switch statement, a container of std::function, or a heterogeneous container of polymorphic "command" objects.
A solution based on a switch statement is pretty trivial, so I won't bother showing an example.
A std::function is a polymorphic wrapper around a function-like object. You can use a container of std::function to build a sort of dispatch table.
struct StringMatch
{
void operator()() const
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
};
struct SquareRoot
{
void operator()() const
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
};
int main()
{
const std::map<int, std::function> commands =
{
{1, StringMatch()},
{2, SquareRoot()},
};
int commandId = 0;
std::cin >> commandId;
auto found = command.find(commandId);
if (found != commands.end())
(*found->second)();
else
std::cout << "Unknown command";
return 0;
}
The map can of course be replaced by a flat array or vector, but then you need to worry about "holes" in the command ID range.
If you need your command objects to be able to do more then execute themselves (like having properties, or support undo/redo), you can use a solution that uses polymorphism and is inspired by the traditional Command Pattern.
class Command
{
public:
virtual ~Command() {}
virtual void execute();
virtual std::string name() const;
virtual std::string description() const;
};
class StringMatch : public Command
{
public:
void execute() override
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
std::string name() const override {return "StringMatch";}
std::string description() const override {return "Matches strings";}
};
class SquareRoot : public Command
{
public:
void execute() override
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
std::string name() const override {return "SquareRoot";}
std::string description() const override {return "Computes square root";}
};
int main()
{
constexpr int helpCommandId = 0;
const std::map<int, std::shared_ptr<Command>> commands =
{
{1, std::make_shared<StringMatch>()},
{2, std::make_shared<SquareRoot>()},
};
int commandId = 0;
std::cin >> commandId;
if (commandId == helpCommandId)
{
// Display command properties
for (const auto& kv : commands)
{
int id = kv.first;
const Command& cmd = *kv.second;
std::cout << id << ") " << cmd.name() << ": " << cmd.description()
<< "\n";
}
}
else
{
auto found = command.find(commandId);
if (found != commands.end())
found->second->execute();
else
std::cout << "Unknown command";
}
return 0;
}
Despite C++ being a statically-typed language, there are ways to emulate Javascript-style dynamic variables, such as the JSON for Modern C++ library or Boost.Variant.
Boost.Any can also be used for type erasure of your command arguments, and your command objects/functions would know how to downcast them back to their static types.
But such emulated dynamic variables will not address your need to have different behavior based on user/file input.
One possible approach when you want to do something with a run-time dependent type very locally, is to predict run-time values at the compile time.
using Tuple = std::tuple<int, double, char>;
int type;
std::cin >> type;
switch(type) {
case 0: {
using ItsType = std::tuple_element<0, Tuple>;
break;
}
case 1: {
using ItsType = std::tuple_element<1, Tuple>;
break;
}
default: std::cerr << "char is not handled yet." << std::endl;
break;
}
Only works with small type packs, of course.
Is there a way to access Nth type at runtime?
Yes, although per other answers, it may not be appropriate in this context.
Adapting this answer, you can iterate at compile time, and choose a type.
#include <iostream>
#include <fstream>
#include <string>
#include <type_traits>
#include <tuple>
#include <cmath>
std::ifstream in("my.txt");
void do_something(const std::string& x)
{
std::cout << "Match " << x << '\n';
}
void do_something(int x)
{
std::cout << "Sqrt of " << x << " = " << std::sqrt(x) << '\n';
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I == sizeof...(Tp)> action_on_index_impl(size_t)
{ // reached end with I==number of types: do nothing
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I < sizeof...(Tp)> action_on_index_impl(size_t i)
{
if (i == I){
// thanks to https://stackoverflow.com/a/29729001/834521 for following
std::tuple_element_t<I, std::tuple<Tp...>> x{};
in >> x;
do_something(x);
}
else
action_on_index_impl<I+1, Tp...>(i);
}
template<typename... Tp> void action_on_index(size_t i)
{
// start at the beginning with I=0
action_on_index_impl<0, Tp...>(i);
}
int main()
{
int i{};
while(in >> i, in)
action_on_index<std::string, int>(i);
return 0;
}
with my.txt
0 hello
1 9
0 world
1 4
output
Match hello
Sqrt of 9 = 3
Match world
Sqrt of 4 = 2
I needed to know how to access Nth type at runtime in a different context, hence my answer here (I wonder if there is a better way, particularly in C++14/17).
Edit: Completely rewrote the question to address suggestions in comments
In a large project that I participate in, there are a lot of classes that wrap messages, events, etc. They do not have a common ancestor and were (and still are) written by different people in different groups.
Most of these classes (or structs) have public members indicating error codes and descriptions. However, since they are used mostly within a single group and conventions are pretty loose, some of them name the members errStr, while others use errDesc.
For example:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
I am trying to write a function template that will accept an object and print out the value of the whatever member variable that it has.
In pseudocode:
template<typename T>
bool logError(T const& x)
{
if (x.errCode == 0)
return true;
// if (T::errStr exists)
// log(x.errStr);
// else if (T::errDesc exists)
// log(x.errDesc);
return false;
}
What complicates matters is that the compiler that we use is VS2012, which is not fully C++11 compliant.
I have been messing with std::enable_if, std::is_same, etc for a while and so far the only result is an impressive collection of different compiler errors.
I was pointed to this by #T.C.
While it turned out to work quite well, it appears clunky and I was wondering if it can be simplified, or another solution offered, using the C++11 features that VS2012 supports.
Thank you!
In principle you can use SFINAE to detect the relevant member, but with C++03 (your compiler's standard) this yields complex, verbose code that's easy to break by maintenance – I give a complete example at the end below. The relevant techniques are covered in umpteen places on the web. E.g. I googled "c++ detect data member SFINAE" and hey presto, some GitHub code, and other examples. The ability to find information on the web, including basic googling, is very important to a developer. So, just try it.
An IMO more practical approach – because it's much simpler code that does not introduce maintenance problems and that goes in the direction you want the code to evolve – is to simply define overloads of an accessor function, one per class, like this:
string errorMessageOf( X const& o ) { return o.errStr; }
string errorMessageOf( Y const& o ) { return o.errDsc; }
Not everything needs to be a template.
Ordinary overloads are nice.
Your desired function template is then
template< class Type >
bool logError( Type const& x )
{
if (x.errCode == 0) return true; // A really dangerous thing to do
// Especially in Windows error code 0 a.k.a. NOERROR etc. is
// sometimes returned by GetLastError for a genuine failure. You
// should better treat it as "unknown cause".
clog << errorMessageOf( x ) << endl;
return not clog.fail(); // The return value is unspecified.
}
Example of instead using C++03 SFINAE, with code that works with Visual C++ 2012, and supporting an arbitrary number of names for the error message data member:
#include <iostream>
#include <stddef.h>
#include <string>
//----------------------------------------------- Machinery:
namespace reusable {
typedef ptrdiff_t Size;
template< Size n >
struct SizeCarrier_ { char nPlusOne[n + 1]; };
template< class Type, Type >
struct TypeFrom_;
} // namespace reusable
namespace my{
using std::string;
namespace impl {
using reusable::SizeCarrier_;
using reusable::TypeFrom_;
struct ErrorMsgMemberId { enum Enum{ noSuch, errStrName, errDescName }; };
template< class Type >
class ErrorMsgMemberId_
{
private:
template< class U >
static SizeCarrier_< ErrorMsgMemberId::errStrName >
memberId( TypeFrom_<string U::*, &U::errStr>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::errDescName>
memberId( TypeFrom_<string U::*, &U::errDesc>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::noSuch>
memberId( ... );
public:
static ErrorMsgMemberId::Enum const value = static_cast<ErrorMsgMemberId::Enum>(
sizeof( memberId< Type >( 0 ).nPlusOne ) - 1
);
};
template< ErrorMsgMemberId::Enum kind >
struct ErrorMsgFunc_;
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errStrName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errStr; }
};
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errDescName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errDesc; }
};
} // namespace impl
template< class Type >
string errorMsgOf( Type const& o )
{
static impl::ErrorMsgMemberId::Enum const member_id =
impl::ErrorMsgMemberId_< Type >::value;
return impl::ErrorMsgFunc_< member_id >()( o );
}
} // namespace my
//----------------------------------------------- Example usage:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
struct Z {
// stuff here...
int errCode;
};
int main()
{
X const x = { 1, "X::errStr" };
Y const y = { 2, "Y::errDesc" };
Z const z = { 3 };
using namespace std;
cout << my::errorMsgOf( x ) << endl;
cout << my::errorMsgOf( y ) << endl;
//cout << my::errorMsgOf( z ) << endl; //! Fails with 'noSuch' in message.
}
I'm trying to find a more elegant solution for some code I'm working on at the moment. I have data that needs to be stored then moved around, but I don't really want to take up any more space than I need to for the data that is stored.
I have 2 solutions, but neither seem very nice.
Using inheritance and a tag
enum class data_type{
first, second, third
};
class data_base{
public:
virtual data_type type() const noexcept = 0;
};
using data_ptr = data_base*;
class first_data: public data_base{
public:
data_type type() const noexcept{return data_type::first;}
// hold the first data type
};
// ...
Then you pass around a data_ptr and cast it to the appropriate type.
I really don't like this approach because it requires upwards casting and using bare pointers.
Using a union and storing all data types
enum class data_type{
first, second, third
};
class data{
public:
data(data_type type_): type(type_){}
data_type type;
union{
// first, second and third data types stored
};
};
But I don't like this approach because then you start wasting a lot of memory when you have a large data type that may get passed around.
This data will then be passed onto a function that will parse it into a greater expression. Something like this:
class expression{/* ... */};
class expr_type0: public expression{/* ... */};
// every expression type
using expr_ptr = expression*;
// remember to 'delete'
expr_ptr get_expression(){
data_ptr dat = get_data();
// interpret data
// may call 'get_data()' many times
expr_ptr expr = new /* expr_type[0-n] */
delete dat;
return expr;
}
and the problem arrises again, but it doesn't matter in this case because the expr_ptr doesn't need to be reinterpreted and will have a simple virtual function call.
What is a more elegant method of tagging and passing around the data to another function?
It's difficult to envisage exactly what you're looking for without more information. But if I wanted some framework that allowed me to store and retrieve data in some structured way, in as-yet-unknown storage devices this is the kind of way I'd be thinking.
This may not be the answer you're looking for, but I think there'll be concepts here that will inspire you in the right direction.
#include <iostream>
#include <tuple>
#include <boost/variant.hpp>
#include <map>
// define some concepts
// bigfoo is a class that's expensive to copy - so lets give it a shared-handle idiom
struct bigfoo {
struct impl {
impl(std::string data) : _data(std::move(data)) {}
void write(std::ostream& os) const {
os << "I am a big object. Don't copy me: " << _data;
}
private:
std::string _data;
};
bigfoo(std::string data) : _impl { std::make_shared<impl>(std::move(data)) } {};
friend std::ostream& operator<<(std::ostream&os, const bigfoo& bf) {
bf._impl->write(os);
return os;
}
private:
std::shared_ptr<impl> _impl;
};
// all the data types our framework handles
using abstract_data_type = boost::variant<int, std::string, double, bigfoo>;
// defines the general properties of a data table store concept
template<class...Columns>
struct table_definition
{
using row_type = std::tuple<Columns...>;
};
// the concept of being able to store some type of table data on some kind of storage medium
template<class IoDevice, class TableDefinition>
struct table_implementation
{
using io_device_type = IoDevice;
using row_writer_type = typename io_device_type::row_writer_type;
template<class...Args> table_implementation(Args&...args)
: _io_device(std::forward<Args>(args)...)
{}
template<class...Args>
void add_row(Args&&...args) {
auto row_instance = _io_device.open_row();
set_row_args(row_instance,
std::make_tuple(std::forward<Args>(args)...),
std::index_sequence_for<Args...>());
row_instance.commit();
}
private:
template<class Tuple, size_t...Is>
void set_row_args(row_writer_type& row_writer, const Tuple& args, std::index_sequence<Is...>)
{
using expand = int[];
expand x { 0, (row_writer.set_value(Is, std::get<Is>(args)), 0)... };
(void)x; // mark expand as unused;
}
private:
io_device_type _io_device;
};
// model the concepts into a concrete specialisation
// this is a 'data store' implementation which simply stores data to stdout in a structured way
struct std_out_io
{
struct row_writer_type
{
void set_value(size_t column, abstract_data_type value) {
// roll on c++17 with it's much-anticipated try_emplace...
auto ifind = _values.find(column);
if (ifind == end(_values)) {
ifind = _values.emplace(column, std::move(value)).first;
}
else {
ifind->second = std::move(value);
}
}
void commit()
{
std::cout << "{" << std::endl;
auto sep = "\t";
for (auto& item : _values) {
std::cout << sep << item.first << "=" << item.second;
sep = ",\n\t";
}
std::cout << "\n}";
}
private:
std::map<size_t, abstract_data_type> _values; // some value mapped by ascending column number
};
row_writer_type open_row() {
return row_writer_type();
}
};
// this is a model of a 'data table' concept
using my_table = table_definition<int, std::string, double, bigfoo>;
// here is a test
auto main() -> int
{
auto data_store = table_implementation<std_out_io, my_table>( /* std_out_io has default constructor */);
data_store.add_row(1, "hello", 6.6, bigfoo("lots and lots of data"));
return 0;
}
expected output:
{
0=1,
1=hello,
2=6.6,
3=I am a big object. Don't copy me: lots and lots of data
}
I have many classes A, B, C, D, etc that are duck-typed and thus have the same methods and interface but do not inherit from the same class.
E.g.
class A {
public:
void foo();
void bar();
}
class B {
public:
void foo();
void bar();
}
class C {
public:
void foo();
void bar();
}
I want to either map const char * to a corresponding instance of one of these classes at run-time e.g.
"A" -> A a
"B" -> B b
Where here a is some instance of class A.
OR map 'const char *` to the the corresponding type at compile-time e.g.
"A" -> A
I need to use the instance of the object in some other functional call (i.e. call foo() or bar()), but the API can only take a const char * as the underlying objects are abstracted away.
I am working in a large, code-genned codebase so changing the paradigm is not practical.
Perform type-erasure using an adaptor interface and a bunch of concrete adaptors implementing that interface; the adaptors can be instances of a class template.
struct IFooBar {
virtual ~IFooBar() {}
virtual void foo() = 0;
virtual void bar() = 0;
};
template<class T> struct FooBarAdaptor : IFooBar {
T* t;
FooBarAdaptor(T* t) : t{t} {} ~FooBarAdaptor() {}
void foo() override { return t->foo(); }
void bar() override { return t->bar(); }
};
// ...
A a;
B b;
C c;
std::map<std::string, std::unique_ptr<IFooBar>> m;
m["a"] = std::make_unique<FooBarAdaptor<A>>(&a);
m["b"] = std::make_unique<FooBarAdaptor<B>>(&b);
m["c"] = std::make_unique<FooBarAdaptor<C>>(&c);
Fatal allows you to trivially solve the compile time version of your problem using compile-time strings, type maps and string lookup structures.
Let's first start with the headers we'll be using:
// type_map so we can associated one type to another
#include <fatal/type/map.h>
// for efficient compile-time built string lookup structures
#include <fatal/type/string_lookup.h>
// for compile-time string
#include <fatal/type/sequence.h>
In this example, we basically want to associate strings to actions, both represented by types.
struct foo_action {
// FATAL_STR creates a compile-time string, equivalent to
// `using name = fatal::constant_sequence<char, 'f', 'o', 'o'>;`
FATAL_STR(name, "foo");
static void DOIT() { std::cout << "FOO-ACTION"; }
};
struct bar_action {
FATAL_STR(name, "bar");
static void DOIT() { std::cout << "BAR-ACTION"; }
};
struct baz_action {
FATAL_STR(name, "baz");
static void DOIT() { std::cout << "BAZ-ACTION"; }
};
Now we create the mapping from compile-time string to an associated type:
using my_map = fatal::build_type_map<
foo_action::name, foo_action,
bar_action::name, bar_action,
baz_action::name, baz_action
>;
In order to perform an efficient string lookup at runtime, let's create some lookup structure at compile-time since we already have the strings available to the compiler. The actual structure is implementation defined, but it usually uses either a prefix-tree or perfect hashing:
using my_lookup = my_map::keys::apply<fatal::string_lookup>;
Now, we need a visitor that's going to be called whenever there's a match in the lookup.
The visitor will receive the compile-time string as its first parameter, wrapped in a type tag to ensure it's an empty instance.
You can receive any number of additional arguments. In this example, we're receiving a1 and a2 as extra arguments for demonstration purposes. They're not mandatory and could safely be removed:
struct lookup_visitor {
// note that we don't give the type_tag parameter a name
// since we're only interested in the types themselves
template <typename Key>
void operator ()(fatal::type_tag<Key>, int a1, std::string const &a2) const {
// Key is the compile-time string that matched
// now let's lookup the associated type in the map:
using type = typename my_map::template get<Key>;
// at this point you have `type`, which is the type associated
// to `Key` in `my_map`
// TODO: at this point you can do whatever you like with the mapped type
// and the extra arguments. Here we simply print stuff and call a method from
// the mapped type:
std::cout << "performing action from type '" << typeid(type).name()
<< "' (additional args from the call to exact: a1="
<< a1 << ", a2='" << a2 << "'):";
// call the static method `DOIT` from the mapped type
type::DOIT();
std::cout << std::endl;
}
};
All that's left to do now is to look the string up in the lookup structure and call the visitor whenever a match is found.
In the code below, we read the runtime string in from the standard input and look it up in the compile-time generated lookup structure.
As stated above, we're also passing two additional arguments to
exact(). Those arguments are not inspected by exact(), but rather perfectly forwarded to the visitor. They're completely optional and they're here simply to demonstrate how convenient it is to pass additional state to the visitor.
In this example, the additional arguments are 56 and "test":
int main() {
for (std::string in; std::cout << "lookup: ", std::cin >> in; ) {
// exact() calls the visitor and returns true if a match is found
// when there's no match, the visitor is not called and false is returned
bool const found = my_lookup::match<>::exact(
in.begin(), in.end(), lookup_visitor(),
56, "test"
);
if (!found) {
std::cout << "no match was found for string '" << in << '\''
<< std::endl;
}
}
return 0;
}
Below is a sample output from this code:
$ clang++ -Wall -std=c++11 -I path/to/fatal sample.cpp -o sample && ./sample
lookup: somestring
no match was found for string 'somestring'
lookup: test
no match was found for string 'test'
lookup: foo
performing action from type '10foo_action' (additional args from the call to exact: a1=56, a2='test'): FOO-ACTION
lookup: bar
performing action from type '10bar_action' (additional args from the call to exact: a1=56, a2='test'): BAR-ACTION
lookup: ^D
$
The most interesting part about the code above is that in order to support more mappings, all you need to do is add another entry to my_map. The compiler will figure out the rest.
Update: changed code to reflect latest upstream Fatal.
Note: Since you added the requirement that something is added at runtime, you can't use the solution below. I'm also convinced that you are confused about the meaning of duck-typing in C++, as runtime and duck-typing don't work together.
Use a factory template and a bunch of specializations:
template<int type> void create_ducky();
template<> A create_ducky<'A'>() { return A(); }
and so on and then call it like
create_ducky<'A'>().foo();
However, that's complete nonsense, because instead of writing 'A', it is much easier to write A as template parameter. I'm relatively sure that what you want isn't such a good idea or that you are at least following a futile path to that (yet unnamed) goal that you really want to reach.
Perhaps a function returning an instance of boost variant, something like :
using V = boost::variant< A, B, C >;
V MyFactory(const char * m)
{
if (std::string(m) == "A") return V(A());
...
}
You can also instanciate a std::map< std::string, V >.
Boost Fusion and Boost MPL can help:
#include<boost/fusion/container/generation/make_map.hpp>
#include<boost/mpl/char.hpp>
#include<cassert>
#include<boost/fusion/container/generation/make_map.hpp>
#include <boost/fusion/sequence/intrinsic/at_key.hpp>
#include<boost/mpl/char.hpp>
#include<cassert>
struct A{std::string call(){return "a";}};
struct B{std::string call(){return "b";}};
struct C{std::string call(){return "c";}};
int main(){
namespace fus = boost::fusion;
namespace mpl = boost::mpl;
A a{};
B b{};
C c{};
auto mymap = fus::make_map<
mpl::char_<'a'>,
mpl::char_<'b'>,
mpl::char_<'c'>
>(
a, // or use
b,
c
);
// which is of type
// fus::map<
// fus::pair<mpl::char_<'a'>, A>,
// fus::pair<mpl::char_<'b'>, B>,
// fus::pair<mpl::char_<'c'>, char>
// >
// and it is used as:
assert( fus::at_key<mpl::char_<'b'>>(mymap).call() == "b" );
}
(running code: http://coliru.stacked-crooked.com/a/aee0daa07510427e)
Whether this helps or not depends on whether you want runtime polymorphism or compiletime polymorphism (this solution). A wrapper around boost::fusion::map can be made to accept literal chars directly. Also there is a possibility to use compiletime strings.
In your question you say "compiletime or runtime". But, if you need both it is going to be basically "runtime", which means some form of inhertance and pointers (at some level.) For example, std::map<char, BaseofABC*>.
I want to use boost to join string with ",". But I have a vector of shared_ptr which I need to transform to a string.
(dumb way to do it is to use boost::transform to convert my shared pointer to a vector of strings).
But I wanted to do something like this.
NOTE: I am using VS2012 (and gcc 4.5.3 for Linux builds) and boost 1.48.0
C++ code.
std::string A::returnConcatString() const
{
return boost::algorithm::join( sharedPtrList() | boost::adaptors::transformed(
[](B::ConstPtr obj )->std::string
{
return ( boost::format( "%s:%s" ) % obj->string1() % obj->string2() ).str();
} ),
",");
}
(BTW what happends if I use an anonymous function instead of using string2()? )
HPP Code.
class A
{
public:
/***code***/
vector< B::ConstPtr > sharedPtrList() const;
std::string returnConcatString() const;
}
class B
{
public:
typedef boost::shared_ptr<const B> ConstPtr;
std::string string1() const;
std::string string2() const;
}
Is there a better way to do this? Can anyone please help me understand my issue?
Also, I came across this link http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3594.html (Which is exactly what I want to mimic)
When I compile this code I get an error.
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(79): error C2903: 'result' : symbol is neither a class template nor a function template
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(87) : see reference to class template instantiation 'boost::detail::result_of_nested_result<F,FArgs>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(33) : see reference to class template instantiation 'boost::detail::tr1_result_of_impl<F,FArgs,HasResultType>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &),
HasResultType=false
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(81) : see reference to class template instantiation 'boost::tr1_result_of<F>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/mpl/eval_if.hpp(41) : see reference to class template instantiation 'boost::result_of<F>' being compiled
EDIT: Thanks to an [utnapistim] idea. I am using this for now. But I really wanted to write a one-liner :).
I ended up doing this.
std::string ret;
std::for_each ( array.begin(), array.end(), [&ret](B::ConstPtr firmware)
{
ret.append( ( boost::format( "[%s:%s]" ) % firmwareTypeToString( firmware->firmwareType() ) % firmware->version() ).str() );
}
);
I'd just write it like this:
std::string returnConcatString() const {
std::ostringstream os;
for(auto& b : sharedPtrList)
os << b->string1() << ':' << b->string2() << ',';
auto s = os.str();
if (!s.empty())
s.resize(s.size()-1);
return s; // moves
}
Amazingly, the compile times are better, and the runtime will be a lot better than your code would achieve.
See it Live On Coliru
And if you really cared about performance, I'd suggest Boost Karma:
std::string returnConcatString() const {
if (sharedPtrList.empty())
return {};
std::string result;
result.reserve(20 * sharedPtrList.size()); // average length preallocate?
auto out = back_inserter(result);
namespace k = boost::spirit::karma;
for(auto& b : sharedPtrList)
k::generate(out, k::string << ':' << k::string << ',', b->string1(), b->string2());
result.resize(result.size()-1);
return result; // moves
}
See it Live On Coliru too
A performance comparison:
As you can see, the stringstream approach is only bad at small collections.
Raw data and benchmark code
I use this:
/*
* File: ostream_join_iterator.hpp
* Author: utnapistim :)
*
* Created on July 13, 2013, 1:14 AM
*/
#ifndef OSTREAM_JOIN_ITERATOR_HPP
#define OSTREAM_JOIN_ITERATOR_HPP
/**
* #brief Implements join functionality directing into an ostream
*
* This class provides an iterator for writing into an ostream.
* The type T is the only type written by this iterator and there must
* be an operator << (T) defined.
*
* #remarks This class implements functionality similar to
* std::ostream_iterator except it does not print a separator after the
* last element.
*
* #param Tp The type to write to the ostream.
* #param CharT The ostream char_type.
* #param Traits The ostream char_traits.
*/
template<typename T, typename C=char, typename Tr=std::char_traits<C> >
class ostream_join_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef C char_type;
typedef Tr traits_type;
typedef std::basic_string<C, Tr> splitter_type;
typedef std::basic_ostream<C, Tr> ostream_type;
private:
ostream_type *out_;
splitter_type splitter_;
bool at_first_;
public:
ostream_join_iterator(ostream_type& out)
: out_{&out}
, splitter_{}
, at_first_{true}
{
}
/**
* Construct from an ostream.
*
* #remarks The delimiter is not copied, and thus must not be destroyed
* while this iterator is in use.
*
* #param out Underlying ostream to write to.
* #param splitter CharT delimiter string to insert.
*/
ostream_join_iterator(ostream_type& out, const char_type* splitter)
: out_{&out}
, splitter_{splitter}
, at_first_{true}
{
}
/// Copy constructor.
ostream_join_iterator(const ostream_join_iterator& other)
: out_{other.out_}
, splitter_{other.splitter_}
, at_first_{other.at_first_}
{
}
ostream_join_iterator& operator=(const T& value)
{ // add separator before the value, if not at first element
if((not splitter_.empty()) and (not at_first_))
*out_ << splitter_;
*out_ << value;
at_first_ = false;
return *this;
}
ostream_join_iterator& operator=(ostream_join_iterator temp)
{
using std::swap;
swap(out_, temp.out_);
swap(splitter_, temp.splitter_);
swap(at_first_, temp.at_first_);
return *this;
}
ostream_join_iterator&
operator*() {
return *this;
}
ostream_join_iterator&
operator++() {
return *this;
}
ostream_join_iterator&
operator++(int) {
return *this;
}
};
template <typename T> using join = ostream_join_iterator<T>;
template <typename T> using wjoin = ostream_join_iterator<T, wchar_t>;
#endif /* OSTREAM_JOIN_ITERATOR_HPP */
Usage:
using namespace std;
ostringstream sql;
sql << "SELECT ";
transform(fields_.begin(), fields_.end(), join<string>{sql, ", "},
[](const field& f) { return f.escaped_name(); });
sql << " FROM " << name_;
The transform call can easily be paced into a convenience function.