Is boost::lexical_cast redundant with c++11 stoi, stof and family? - c++

Is boost::lexical_cast redundant now that C++11 introduces stoi, stof and family, or is there any reason to still use it? (apart from not having a C++11 compiler) Do they provide exactly the same functionality?

boost::lexical_cast
handles more kinds of conversion, including iterator pairs, arrays, C strings, etc.
offers the same generic interface (sto* have different names for different types)
is locale-sensitive (sto*/to_string are only in part, e.g. lexical_cast can process thousands separators, while stoul usually doesn't)

boost::lexical_cast gives you a uniform interface across types which is often very important in generic code.
In general, consistent interface across types for same functionality allows generic code better. For example, following can be used as generic parser from string tokens to std::tuple:
template<typename T>
void fill(T& item, const std::string& token){
item = boost::lexical_cast<T>(token)
}
template<int N, typename ...Ts>
void parse(std::integral_constant<int, N>, std::tuple<Ts...>& info, std::vector<std::string>& tokens) {
fill(std::get<N>(info), tokens[N]);
parse(std::integral_constant<int, N - 1>, info, tokens);
}
template<typename ...Ts>
void parse(std::integral_constant<int, 0>, std::tuple<Ts...>& info, std::vector<std::string>& tokens) {
fill(std::get<0>(info), tokens[0]);
}
Instead of tuple, I often use boost fusion struct to deserialize some tokenized strings directly into a struct in a generic way.

Performance wise, you could do the comparison using the following code (it's a variation of my post here)
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <chrono>
#include <random>
#include <exception>
#include <type_traits>
#include <boost/lexical_cast.hpp>
using namespace std;
// 1. A way to easily measure elapsed time -------------------
template<typename TimeT = std::chrono::milliseconds>
struct measure
{
template<typename F>
static typename TimeT::rep execution(F const &func)
{
auto start = std::chrono::system_clock::now();
func();
auto duration = std::chrono::duration_cast< TimeT>(
std::chrono::system_clock::now() - start);
return duration.count();
}
};
// -----------------------------------------------------------
// 2. Define the convertion functions ========================
// A. Using boost::lexical_cast ------------------------------
template<typename Ret>
Ret NumberFromString(string const &value) {
return boost::lexical_cast<Ret>(value);
}
// B. Using c++11 stoi() -------------------------------------
int IntFromString(string const &value) {
return std::stoi(value);
}
// C. Using c++11 stof() -------------------------------------
float FloatFromString(string const &value) {
return std::stof(value);
}
// ===========================================================
// 3. A wrapper to measure the different executions ----------
template<typename T, typename F> long long
MeasureExec(std::vector<string> const &v1, F const &func)
{
return measure<>::execution([&]() {
for (auto const &i : v1) {
if (func(i) != NumberFromString<T>(i)) {
throw std::runtime_error("FAIL");
}
}
});
}
// -----------------------------------------------------------
// 4. Machinery to generate random numbers into a vector -----
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
FillVec(vector<T> &v)
{
mt19937 e2(1);
uniform_int_distribution<> dist(3, 1440);
generate(v.begin(), v.end(), [&]() { return dist(e2); });
}
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type
FillVec(vector<T> &v)
{
mt19937 e2(1);
uniform_real_distribution<> dist(-1440., 1440.);
generate(v.begin(), v.end(), [&]() { return dist(e2); });
}
template<typename T>
void FillVec(vector<T> const &vec, vector<string> *result)
{
result->resize(vec.size());
for (size_t i = 0; i < vec.size(); i++)
result->at(i) = boost::lexical_cast<string>(vec[i]);
}
// -----------------------------------------------------------
int main()
{
std::vector<int> vi(991908);
FillVec(vi);
std::vector<float> vf(991908);
FillVec(vf);
std::vector<string> vsi, vsf;
FillVec(vi, &vsi);
FillVec(vf, &vsf);
cout << "C++ 11 stof function .. " <<
MeasureExec<float>(vsf, FloatFromString) << endl;
cout << "Lexical cast method ... " <<
MeasureExec<float>(vsf, NumberFromString<float>) << endl;
cout << endl << endl;
cout << "C++ 11 stoi function .. " <<
MeasureExec<int>(vsi, IntFromString) << endl;
cout << "Lexical cast method ... " <<
MeasureExec<int>(vsi, NumberFromString<int>) << endl;
return 0;
}
When executed with
g++ -std=c++11 -Ofast -march=native -Wall -pedantic main.cpp && ./a.out
The results are
C++ 11 stof function .. 540
Lexical cast method ... 559
C++ 11 stoi function .. 117
Lexical cast method ... 156
The C++11 specialized functions certainly seem to perrform better. But they are exactly that, specialized, and as such make the construction of abstract interfaces harder than lexical_cast

boost::lexical_cast is more than converting to a distinct set of types:
struct A {};
std::ostream& operator << (std::ostream& stream, const A&) {
return stream;
}
struct B {};
std::istream& operator >> (std::istream& stream, B&) {
return stream;
}
int main(){
A a;
B b = boost::lexical_cast<B>(a);
}
Its strength and weakness is the acceptance of any pair of types for the conversion through an intermediate std::stringstream (where an optimized algorithm is or is not applied).

Related

printf like utility in c++ without format specifier?

I am trying to write a function that can convert its argument into a string. However, I am finding it difficult to unpack the parameter pack.
Here is the code that I have written:
#include <iostream>
#include <sstream>
template <typename... T>
std::string StringFormatter(T... values)
{
std::ostringstream out;
for (auto&& x : { values... }) {
out << x;
}
return out.str();
}
int main()
{
auto&& i = StringFormatter("One ", "two"); //Success
auto&& j = StringFormatter("one ", 1, "two", 2.0); //Fails
std::cout << i;
}
I know that the above code is failing because the initializer list accepts only single type arguments.
I have tried a recursive approach to achieve the above implementation, but no luck.
If you can suggest a better way to achieve this, it would be a great help.
You can achieve this with C++17's fold expression:
template <typename... T>
std::string StringFormatter(T... values)
{
std::ostringstream out;
(out << ... << values);
return out.str();
}
In short:
If you don't have a C++17 compiler, you can rely on the int array trick:
template <typename... T>
std::string StringFormatter(T... values) {
std::ostringstream out;
int arr[] = { 0, (out << values, void(), 0)... };
return out.str();
}
The apparently useless 0 at the start of the array is required in the case the parameter pack is empty because you can't instantiate an array of size 0. The void() is there to circumvent hypothetical operator, overloads.
The evaluation order is guaranteed and the compiler should be able to optimize away the array in the resulting binary.
In depth:
This technique is the pre-C++17 way of doing fold expressions. Basically we create an array of sizeof...(T) + 1 elements (all 0). The catch here is that we are using properties of the , operator to run the operation we want on each element of the parameter pack.
Let's forget about the parameter pack and the template for a moment.
When you do:
something, other_thing
Assuming there is no overload to the , operator, the statement is evaluated to other_thing. But that doesn't mean that something is ignored. Its value is just discarded in favor of other_thing. We are using that property for our little trick.
int x = 0;
int a[] = { 0, (++x, 0) }; // a is {0, 0}, x is 1
Now since you can overload operator,, we just add an additional statement to avoid this hypothetical overload:
(something, void(), 0)
Since operator, is a binary operator, an overloaded version of it cannot have only one argument. By adding a statement evaluating to void we are preventing any hypothetical overload to be picked and therefore are sure we end up with our 0.
The last step is to combine that with our parameter pack and perform pack expansion on the resulting statement:
(out << values, void(), 0)...
There are better ways to do it now (with a fold expression), but if you want to use the recursive approach, it can look something like this:
#include <sstream>
#include <string>
#include <iostream>
template <class T>
std::string stringify(T const &t) {
std::stringstream b;
b << t;
return b.str();
}
template<typename T, typename... Args>
std::string stringify(T arg, const Args&... args) {
return stringify(arg) + stringify(args...);
}
int main() {
std::string three{" three"};
std::cout << stringify("one: ", 1, " two: ", 2, three, "\n");
return 0;
}
You should be able to use this with essentially any type that supports stream insertion. If you're passing enough parameters that the quadratic time on the number of parameters is a concern, 1) go see a psychiatrist, and 2) feel free to use code more on this general order:
#include <sstream>
#include <string>
#include <iostream>
namespace detail {
template <class T>
void stringify(std::ostringstream &b, T const &t) {
b << t;
}
template<typename T, typename... Args>
void stringify(std::ostringstream &os, T arg, const Args&... args) {
stringify(os, arg);
stringify(os, args...);
}
}
template <typename ...Args>
std::string stringify(const Args &...args) {
std::ostringstream os;
detail::stringify(os, args...);
return os.str();
}
int main() {
std::string three{" three"};
std::cout << stringify("one: ", 1, " two: ", 2, three, "\n");
}
...but definitely see a psychiatrist first. If you're passing enough arguments for it to matter, you're clearly doing something horribly wrong.

Template to match custom functors or stod, stoi, etc

I'm trying to store key-value parameters as string in a class named ModelConfig. Then I would like to automatically convert these values into specific types, either with custom conversion function or with standard functions stod, stof, stoi, and the like.
My class successfully parses parameters if I provide a custom conversion function, but I can't figure how to also accept standard functions. This is my approach:
class ModelConfig
{
public:
ModelConfig(void) = default;
void addParam(std::string pname, std::string pvalue) {
m_params[pname] = pvalue;
}
template <class F, typename... Args, class T = typename std::result_of<F&&(const std::string&, Args...)>::type>
T getParam(std::string pname, F&& pconv_functor) const
{
return pconv_functor(m_params.at(pname));
}
private:
std::map<std::string, std::string> m_params;
};
The class above, can be tested with:
#include <iostream>
#include <map>
#include <functional>
#include "ModelConfig.hpp"
int main(void)
{
ModelConfig mc;
mc.addParam("p1_float", "123.4");
mc.addParam("p2_double", "56.7");
mc.addParam("p3_bool", "true");
mc.addParam("p4_int", "-321");
auto functord = [](const std::string& s) {
return std::stod(s);
};
std::cout << mc.getParam("p2_double", functord) << "\n"; // OK.
std::cout << mc.getParam("p2_double", std::stod) << "\n"; // Error.
return 0;
}
How can I modify getParam to accept functions where their first argument is a string but which can have others with default values?
std::stod is overloaded, thus the compiler can't deduce which function to use.
You can use macro to write a generic wrapper:
#define wrapper(f) \
( [] (auto&&... args) -> decltype(auto) { \
return f(std::forward<decltype(args)>(args)...); \
} )
Then call it by:
std::cout << mc.getParam("p2_double", wrapper(std::stod)) << "\n";
An alternative and, IMO, better design is to store values as std/boost::variant<bool, long, double, std::string> and convert it to/from string during I/O. This also detects config file errors early on load, rather than on first value access which could happen much later and crash your application in front of the user.
Requiring the user of this API to always pass a conversion function is cumbersome. You can use boost::lexical_cast for converting strings to T:
#include <string>
#include <iostream>
#include <unordered_map>
#include <boost/lexical_cast.hpp>
struct ConvertProxy {
std::string const* value_;
template<class T>
T as() const {
return boost::lexical_cast<T>(*value_);
}
template<class T>
operator T() const {
return this->as<T>();
}
};
class ModelConfig {
std::unordered_map<std::string, std::string> m_params;
public:
void addParam(std::string pname, std::string pvalue) {
m_params[pname] = pvalue;
}
ConvertProxy getParam(std::string pname) const {
return {&m_params.at(pname)};
}
};
int main() {
ModelConfig mc;
mc.addParam("p1_float", "123.4");
mc.addParam("p2_double", "56.7");
mc.addParam("p3_bool", "true");
mc.addParam("p4_int", "-321");
// Example syntax.
double d1 = mc.getParam("p2_double");
auto d2 = mc.getParam("p2_double").as<double>();
auto d3 = static_cast<double>(mc.getParam("p2_double"));
std::cout << mc.getParam("p2_double").as<double>() << "\n";
std::cout << static_cast<double>(mc.getParam("p2_double")) << "\n";
}
The interface of boost::lexical_cast enables an easy solution here. If you cannot use boost::lexical_cast you should probably code up your own with a similar interface.
You can do this with no third party lib and without using preprocessor directives if you need:
by explicitely casting your standard functions pointers. Standard functions are overloaded for string and wstring so the compiler needs our help to determine which one to apply
and by slightly changing your functor's signature to adapt it to the signature of these standard functions as they have a second parameter.
These changes would be slight actually:
In ModelConfig:
class ModelConfig
{
[...]
// Adapted the functor's signature to comply to standard functions' signatures:
template <class F, typename... Args, class T = typename std::result_of<F && (const std::string&, size_t *)>::type>
T getParam(std::string pname, F&& pconv_functor) const
{
return pconv_functor(m_params.at(pname), 0);
}
[...]
};
In main():
int main(void)
{
[...]
// Adapted the functor to standard functions' signature
auto functord = [](const std::string& s, size_t * pos) {
return std::stod(s, pos);
};
// Unchanged, no need
std::cout << mc.getParam("p2_double", functord) << "\n"; // Still OK.
// Cast to determine which overload to use. The typedef helps having things readable.
typedef double(*StandardFunctionSignature)(const std::string&, size_t*);
std::cout << mc.getParam("p2_double", static_cast<StandardFunctionSignature>(std::stod)) << "\n"; // NO Error, it works now.
[...]
}
If you know the signature of the passed in overload set, you can make an additional overload that captures a specific function pointer from that set.
template <class F>
auto getParam(std::string pname, F&& pconv_functor) const
{
return pconv_functor(m_params.at(pname));
}
template <class F>
auto getParam(std::string pname, F(*pconv_functor)(const std::string&, std::size_t*)) const
{
return pconv_functor(m_params.at(pname), 0);
}
This has some obvious limitations, but can be useful in certain situations.

How do you create a generic parser using qi?

I am attempting to create generic parser-elements using qi as I unfortunately (MSVC must be supported) can not use X3.
The idea is to have a templated struct:
template<class T> struct parse_type;
Which I could use like this:
template<class T> T from_string(std::string const& s)
{
T res;
parse_type<T> t;
...
if (phrase_parse(...,parse_type<T>(),...,t))
}
or specialise like this
template<class T,class Alloc>
struct parse_type<std::vector<T,Alloc>>
{
// Parse a vector using rule '[' >> parse_type<T> % ',' > ']';
}
The primary purpose is to allow for easy parsing of e.g. std::tuple, boost::optional and boost::variant (The last one can not be automatic due to the greedy nature of qi).
I would appreciate feedback as to how approach this. Currently I base my struct on qi::grammar, but grammar is not supported in X3 and I would like to use X3 when MSVC compiles this, and I am also a little bit uncomfortable with having to provide the skipper.
An alternative would be to have a static function in parse_type that returns the appropriate rule. I am considering if this is a cleaner approach?
Any feedback will be appreciated.
Update2: Replaced code-snippet with compilable example that fails at runtime. Here is the code:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
#include <string>
#include <iostream>
#include <iostream>
// Support to simplify
using iter = std::string::const_iterator;
void print(std::vector<int> const& v)
{
std::cout << '[';
for (auto i: v) std::cout << i << ',';
std::cout << "]";
}
namespace qi = boost::spirit::qi;
// My rule factory - quite useless if you do not specialise
template<class T> struct ps_rule;
// An example of using the factory
template<class T>
T from_string(std::string const& s)
{
T result;
iter first { std::begin(s) };
auto rule = ps_rule<T>::get();
phrase_parse(first,std::end(s),rule,qi::space,result);
return result;
}
// Specialising rule for int
template<>
struct ps_rule<int>
{
static qi::rule<iter,int()> get() { return qi::int_; }
};
// ... and for std::vector (where the elements must have rules)
template<class T,class Alloc>
struct ps_rule<std::vector<T,Alloc>>
{
static qi::rule<iter,std::vector<T,Alloc>()> get()
{
qi::rule<iter,std::vector<T,Alloc>()> res;
res.name("Vector");
res =
qi::lit('{')
>> ps_rule<T>::get() % ','
>> '}';
return res;
}
};
int main()
{
// This one works like a charm.
std::cout << ((from_string<int>("100") == 100) ? "OK\n":"Failed\n");
std::vector<int> v {1,2,3,4,5,6};
// This one fails
std::cout << ((from_string<std::vector<int>>("{1,2,3,4,5,6}") == v) ? "OK\n":"Failed\n");
}
The code fails in boost/function_template.hpp line 766:
result_type operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return get_vtable()->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
This code is a member function in boost::function4
,boost::fusion::vector0 > &
,boost::spirit::unused_type const&>
and the problem is that get_vtable returns an invalid pointer.
Your main problem is that the copy constructor for qi::rule takes a reference to the original rule, which in your case is a local variable. One way you can avoid this problem is by using qi::rule's copy member function but this requires changing slightly the return type of your specialization of ps_rule.
static typename boost::proto::terminal<qi::rule<iter,std::vector<T,Alloc>()>>::type get()
{
//[...] (same as before)
return res.copy();
}
Once you do that, the same problem arises with your ps_rule<int> even though it seemed to work in isolation. You could do something analogous but in this case the rule is not required, it would be better (even from a performance point of view) to just use something like:
static qi::int_type get() { return qi::int_; }
Full Sample (Running on WandBox)
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
// Support to simplify
using iter = std::string::const_iterator;
void print(std::vector<int> const& v)
{
std::cout << '[';
for (auto i: v) std::cout << i << ',';
std::cout << "]";
}
namespace qi = boost::spirit::qi;
// My rule factory - quite useless if you do not specialise
template<class T> struct ps_rule;
// An example of using the factory
template<class T>
T from_string(std::string const& s)
{
T result;
iter first { std::begin(s) };
auto rule = ps_rule<T>::get();
qi::phrase_parse(first,std::end(s),rule,qi::space,result);
return result;
}
// Specialising rule for int
template<>
struct ps_rule<int>
{
static qi::int_type get() { return qi::int_; }
};
// ... and for std::vector (where the elements must have rules)
template<class T,class Alloc>
struct ps_rule<std::vector<T,Alloc>>
{
static typename boost::proto::terminal<qi::rule<iter,std::vector<T,Alloc>()>>::type get()
{
qi::rule<iter,std::vector<T,Alloc>()> res;
res.name("Vector");
res =
qi::lit('{')
>> ps_rule<T>::get() % ','
>> '}';
return res.copy();
}
};
int main()
{
// This one works like a charm.
std::cout << ((from_string<int>("100") == 100) ? "OK\n":"Failed\n");
std::vector<int> v {1,2,3,4,5,6};
std::cout << ((from_string<std::vector<int>>("{1,2,3,4,5,6}") == v) ? "OK\n":"Failed\n");
std::vector<std::vector<int> > vv {{1,2,3},{4,5,6}};
std::cout << ((from_string<std::vector<std::vector<int>>>("{{1,2,3},{4,5,6}}") == vv) ? "OK\n":"Failed\n");
}
PS: You can save lots of specializations if you use Spirit's own machinery to create parsers automatically in your primary template. Here is an example.

struct to/from std::tuple conversion

Assuming I have struct and std::tuple with same type layout:
struct MyStruct { int i; bool b; double d; }
using MyTuple = std::tuple<int,bool,double>;
Is there any standartized way to cast one to another?
P.S. I know that trivial memory copying can do the trick, but it is alignment and implementation dependent
We can use structured bindings to convert a struct into a tuple with a bit of work.
Struct-to-tuple is very awkward.
template<std::size_t N>
struct to_tuple_t;
template<>
struct to_tuple_t<3> {
template<class S>
auto operator()(S&& s)const {
auto[e0,e1,e2]=std::forward<S>(s);
return std::make_tuple(e0, e1, e2);
}
};
Now, write a to_tuple_t for each size you want to support. This gets tedious. Sadly I know of no way to introduce a parameter pack there.
template<std::size_t N, class S>
auto to_tuple(S&& s) {
return to_tuple_t<N>{}(std::forward<S>(s));
}
I know of no way to calculate the value of N required either. So you'd have to type the 3 in auto t = to_tuple<3>(my_struct); when you call it.
I am not a master of structured bindings. There is probably a && or & or a decltype that would permit perfect forwarding on these lines:
auto[e0,e1,e2]=std::forward<S>(s);
return std::make_tuple(e0, e1, e2);
but without a compiler to play with, I'll be conservative and make redundant copies.
Converting a tuple into a struct is easy:
template<class S, std::size_t...Is, class Tup>
S to_struct( std::index_sequence<Is...>, Tup&& tup ) {
using std::get;
return {get<Is>(std::forward<Tup>(tup))...};
}
template<class S, class Tup>
S to_struct( Tup&&tup ) {
using T=std::remove_reference_t<Tup>;
return to_struct(
std::make_index_sequence<std::tuple_size<T>{}>{},
std::forward<Tup>(tup)
);
}
SFINAE support based off tuple_size might be good for to_struct.
The above code works with all tuple-likes, like std::pair, std::array, and anything you custom-code to support structured bindings (tuple_size and get<I>).
Amusingly,
std::array<int, 3> arr{1,2,3};
auto t = to_tuple<3>(arr);
works and returns a tuple with 3 elements, as to_tuple is based on structured bindings, which work with tuple-likes as input.
to_array is another possibility in this family.
Unfortunately there is no automatic way to do that, BUT an alternative is adapt the struct to Boost.Fusion sequence. You do this once and for all for each new class.
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
...
struct MyStruct { int i; bool b; double d; }
BOOST_FUSION_ADAPT_STRUCT(
MyStruct,
(int, i)
(bool, b)
(double, d)
)
The use MyStruct as if it where a Fusion.Sequence (it fits generically almost everywhere you already use std::tuple<...>, if you make those functions generic.) As a bonus you will not need to copy your data members at all.
If you really need to convert to std::tuple, after "Fusion-adapting" you can do this:
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/zip.hpp>
...
auto to_tuple(MyStruct const& ms){
std::tuple<int, bool, double> ret;
auto z = zip(ret, ms);
boost::fusion::for_each(z, [](auto& ze){get<0>(ze) = get<1>(ze);});
// or use boost::fusion::copy
return ret;
}
The truth is that std::tuple is a half-backed feature. It is like having STD containers and no algorithms. Fortunatelly we have #include <boost/fusion/adapted/std_tuple.hpp> that allows us to do amazing things.
Full code:
By including the std_tuple.hpp header from Boost.Fusion std::tuple is automatically adapted to a Boost.Fusion sequence, thus the following is possible by using Boost.Fusion as a bridge between your struct and std::tuple:
#include <iostream>
#include <string>
#include <tuple>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/algorithm/auxiliary/copy.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
struct foo
{
std::string a, b, c;
int d, e, f;
};
BOOST_FUSION_ADAPT_STRUCT(
foo,
(std::string, a)
(std::string, b)
(std::string, c)
(int, d)
(int, e)
(int, f)
)
template<std::size_t...Is, class Tup>
foo to_foo_aux(std::index_sequence<Is...>, Tup&& tup) {
using std::get;
return {get<Is>(std::forward<Tup>(tup))...};
}
template<class Tup>
foo to_foo(Tup&& tup) {
using T=std::remove_reference_t<Tup>;
return to_foo_aux(
std::make_index_sequence<std::tuple_size<T>{}>{},
std::forward<Tup>(tup)
);
}
template<std::size_t...Is>
auto to_tuple_aux( std::index_sequence<Is...>, foo const& f ) {
using boost::fusion::at_c;
return std::make_tuple(at_c<Is>(f)...);
}
auto to_tuple(foo const& f){
using T=std::remove_reference_t<foo>;
return to_tuple_aux(
std::make_index_sequence<boost::fusion::result_of::size<foo>::type::value>{},
f
);
}
int main(){
foo f{ "Hello", "World", "!", 1, 2, 3 };
std::tuple<std::string, std::string, std::string, int, int, int> dest = to_tuple(f);
// boost::fusion::copy(f, dest); // also valid but less general than constructor
std::cout << std::get<0>(dest) << ' ' << std::get<1>(dest) << std::get<2>(dest) << std::endl;
std::cout << at_c<0>(dest) << ' ' << at_c<1>(dest) << at_c<2>(dest) << std::endl; // same as above
foo f2 = to_foo(dest);
std::cout << at_c<0>(f2) << ' ' << at_c<1>(f2) << at_c<2>(f2) << std::endl;
}
I will not recommend reinterpret_cast<std::tuple<...>&>(mystructinstance.i) because that will result in negative votes and it is not portable.
Is there any standartized way to cast one to another?
There is no way to "cast" the one to the other.
The easiest may be to use a std::tie to pack the tuple out into the struct;
struct MyStruct { int i; bool b; double d; };
using MyTuple = std::tuple<int,bool,double>;
auto t = std::make_tuple(42, true, 5.1);
MyStruct s;
std::tie(s.i, s.b, s.d) = t;
Demo.
You can further wrap this up in higher level macros or "generator" (make style) functions, e.g;
std::tuple<int, bool, double> from_struct(MyStruct const& src)
{
return std::make_tuple(src.i, src.b, src.d);
}
MyStruct to_struct(std::tuple<int, bool, double> const& src)
{
MyStruct s;
std::tie(s.i, s.b, s.d) = src;
return s;
}
I know that trivial memory copying can do the trick, but it is alignment and implementation dependent?
You mention the "trivial memory copy" would work - only for copying the individual members. So basically, a memcpy of the entire structure to the tuple and vice-versa is not going to always behave as you expect (if ever); the memory layout of a tuple is not standardised. If it does work, it is highly dependent on the implementation.
Tuple to struct conversion is trivial, but backward I think is impossible at current C++ level in general.
#include <type_traits>
#include <utility>
#include <tuple>
namespace details
{
template< typename result_type, typename ...types, std::size_t ...indices >
result_type
make_struct(std::tuple< types... > t, std::index_sequence< indices... >) // &, &&, const && etc.
{
return {std::get< indices >(t)...};
}
}
template< typename result_type, typename ...types >
result_type
make_struct(std::tuple< types... > t) // &, &&, const && etc.
{
return details::make_struct< result_type, types... >(t, std::index_sequence_for< types... >{}); // if there is repeated types, then the change for using std::index_sequence_for is trivial
}
#include <cassert>
#include <cstdlib>
int main()
{
using S = struct { int a; char b; double c; };
auto s = make_struct< S >(std::make_tuple(1, '2', 3.0));
assert(s.a == 1);
assert(s.b == '2');
assert(s.c == 3.0);
return EXIT_SUCCESS;
}
Live example.

Retrieve pointer to best match from overload set without calling

For various reasons I need to use 2 phase construction, furthermore the last phase is deferred and performed by another thread, some context:
...
#define BOOST_PP_LOCAL_MACRO(n) \
template < typename ConnectionType, BOOST_PP_ENUM_PARAMS(n, typename T) > \
boost::shared_ptr< ConnectionType > Connect( BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg) ) \
{ \
boost::shared_ptr< ConnectionType > con( boost::make_shared< ConnectionType >() ); \
boost::mutex::scoped_lock sl( m_AddNetworkJobMutex ); \
m_NetworkJobs.push_back( boost::bind( static_cast< void ( ConnectionType::* )( BOOST_PP_ENUM_PARAMS(n,T) ) >( &ConnectionType::Init ), con, BOOST_PP_ENUM_PARAMS(n, arg) ) ); \
return con; \
}
#define BOOST_PP_LOCAL_LIMITS (1, 5)
#include BOOST_PP_LOCAL_ITERATE()
...
The problem here is that I want to select the best match possible from the overload set for ConnectionType::Init, but the cast is distinct and can't find a perfect match even if some of the arguments are convertible. So the questions becomes: Is it possible to somehow get the type & pointer to the best match from the overload set without actually calling it? Can't use anything which isn't available in C++03.
You can leverage lazy evaluation expression templates.
AFAIK bind expressions are precisely in that family (as are Boost Proto epxressions, Spirit Grammar parse expressions etc.).
Update finally got my act together. However, it only works with callable objects with overloaded operator(). I suppose you can use something like this as glue?
I now show both C++03 and C++11 proofs-of-concept that might help get something of a glue functor built-up around this
The C++03 is near equivalent (see the // TODO in the code)
The C++03 version depends on Boost Typeof and Boost Bind (see Boost Utility doc for result_of for backgrounds on result types of polymorphic function objects)
Both versions live on IdeOne
C++03 (live on https://ideone.com/VHcEC)
Here is a partial port of the C++11 demo (below) into C++03 + Boost:
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/typeof/typeof.hpp>
struct overloaded
{
typedef int result_type;
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
struct factory
{
template <typename T> struct result { typedef BOOST_TYPEOF_TPL(boost::bind(overloaded(), T())) type; };
template <typename T>
typename result<T>::type operator()(const T& t) const
{
return boost::bind(overloaded(), t);
}
};
int main()
{
overloaded foo;
// based on local bind expression:
BOOST_AUTO(unresolved, boost::bind(foo, _1));
std::cout << unresolved("3.14") << std::endl; // should print 1
std::cout << unresolved(3.14) << std::endl; // should print 2
// based on a factory function template
factory makefoo;
std::string str("3.14"); // TODO get rid of this explicit instanciation?
std::cout << makefoo(str)() << std::endl; // should print 1
std::cout << makefoo(3.14)() << std::endl; // should print 2
}
C++11 (live on https://ideone.com/JILEA)
As a simple example, this should work alright:
#include <string>
#include <iostream>
#include <functional>
using namespace std::placeholders;
struct overloaded
{
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
template <typename T>
auto makefoo(const T& t) -> decltype(std::bind(overloaded(), t))
{
return std::bind(overloaded(), t);
}
int main()
{
overloaded foo;
// based on local bind expression:
auto unresolved = std::bind(foo, _1);
std::cout << unresolved(3.14) << std::endl; // should print 2
std::cout << unresolved("3.14") << std::endl; // should print 1
// based on a factory function template
std::cout << makefoo(3.14)() << std::endl; // should print 2
std::cout << makefoo("3.14")() << std::endl; // should print 1
}