I have a
typedef std::tuple<A, B> TupleType;
and would like to use the list of classes
for a "template".
Suppose I have:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
and that I can successfully use it with:
auto my_tuple = parse<A, B>(ifs);
is it possible to avoid having to specify the class list A,B if I already have a
typedef std::tuple<A,B> TupleType;
where the list A,B is already present?
an example:
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <tuple> // std::tuple
class A {
public:
A(std::istream &); // May throw FooBaarException
};
class B {
public:
B(std::istream &); // May throw FooBaarException
};
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
int main() {
std::ifstream ifs;
ifs.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res = EXIT_FAILURE;
try {
ifs.open("/some/file/path", std::ios::in | std::ios::binary);
auto my_tuple = parse<A, B>(ifs); // my_tuple is of the type std::tuple<A,B>
/* Here do something interesting with my_tuple */
res = EXIT_SUCCESS;
} catch (ifstream::failure e) {
std::cerr << "error: opening or reading file failed\n";
} catch (FooBaarException e) {
std::cerr << "error: parsing in a constructor failed\n";
}
return res;
}
The underlying problem in your situation seems to be that you'd like to specialize the function template parse for the special case when the template argument is a std::tuple. Unfortunately, this kind of specialization isn't possible with function templates.
However, it is possible with class templates.
So, as a first step, you could define parse as a static function of a struct, like this:
using std::istream;
using std::tuple;
using std::make_tuple;
struct A { A(const istream &) {} };
struct B { B(const istream &) {} };
template <typename... Args>
struct parser
{
/* Your original function, now inside a struct.
I'm using direct tuple construction and an
initializer list to circumvent the order-of-
construction problem mentioned in the comment
to your question. */
static tuple<Args...> parse(const istream &strm)
{ return tuple<Args...> {Args(strm)...}; }
};
template <typename... Args>
struct parser<tuple<Args...>>
{
/* Specialized for tuple. */
static tuple<Args...> parse(const istream &strm)
{ return parser<Args...>::parse(strm); }
};
You can then call it in the desired way:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parser<tuple_type>::parse(std::cin);
return 0;
}
As a second step, you can define a function template (again) which passes the arguments on to the right specialization of the struct:
template <typename... Args>
auto parse(const istream &strm) -> decltype(parser<Args...>::parse(strm))
{ return parser<Args...>::parse(strm); }
And now you can use it in exactly the way you wanted:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parse<tuple_type>(std::cin);
return 0;
}
(And you can still use it in the old way, too: auto tup = parse<A,B>(std::cin).)
Remark. As mentioned in the comment to parser::parse(), I used direct tuple construction instead of make_tuple to avoid problems with the order of construction of the tuple elements. This is not directly related to your question, but a good thing to do. See how to avoid undefined execution order for the constructors when using std::make_tuple.
There is a standard idiom for this kind of thing. [1]
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
// ... inside here, you have access to the parameter pac
}
Here's an example of using it, which might or might not fit your expectations (your example doesn't really indicate your expected use, since it lacks the typedef you promise in your question): liveworkspace.org.
Since litb raised the point, it is possible to force the tuple-components to be constructed in left-to-right order, illustrating another interesting idiom: comb inheritance. See lws.
(Since lws might disappear again, who knows, I'll paste the code here as well):
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
type value;
template<typename Arg>
TupleMap(Arg&& arg)
: value(T(std::forward<Arg>(arg))...) {
}
operator type() { return value; }
};
//Try it out:
using std::get; // Note 2
using Numbers = std::tuple<char, double, int>;
// Note 3
std::ostream& operator<<(std::ostream& out, const Numbers& n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
std::cout << TupleMap<Numbers>(93.14159);
return 0;
}
[1] At least, I think it's a standard idiom. I use it a lot, and think of it as the "can-opener" pattern.
[2] This is needed (or at least, it's my style) to allow the use of get with tuple-like templates defined outside of std. Doing it this way allows ADL to find the appropriate definition of get without forcing me to add specializations to std::get. In this way, it's similar to the standard ADL idiom for begin and end.
[3] You can search SO for a cool hack to specialize operator<< for all tuples. There's a simpler one which can be used for specific tuples, but that's all off-topic for this question, so I just did something easy and dependency free. Note that this works because of the conversion operator in TupleMap
The basic approach is to create a sequence of indices 0, ..., std::tuple_size<Tuple>::value - 1 as a parameter pack Indices and call your function with parse<typename std::tuple_element<Tuple, Indices>::type...>(stream). You'd probably encapsulate the logic into a function parse_tuple<Tuple>(stream) (and some function this one delegates to) which in the end delegates to parse<...>(stream).
First, here is a class template and a function to create a sequence of indices based on the size of a std::tuple. The indices are needed to obtain a list of type from std::tuple:
template <int... Indices> struct indices;
template <>
struct indices<-1> { // for an empty std::tuple<> there is no entry
typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> { // stop the recursion when 0 is reached
typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
typedef typename indices<Index - 1, Index, Indices...>::type type;
};
template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
return 0;
}
With this in place, it is quite easy to extract the sequence of types from a std::tuple<T...>:
template<typename T, int... Indices>
T parse_tuple(std::istream &stream, indices<Indices...> const*) {
return parse<typename std::tuple_element<Indices, T>::type...>(stream);
}
template <typename T>
T parse_tuple(std::istream& stream) {
return parse_tuple<T>(stream, make_indices<T>());
}
Related
I would like to access a member of std::vector<std::variant> by index. Considering the following snippet:
struct Data {
using data_types = std::variant<std::basic_string<char>, double, int>;
public:
template <class T>
void push_back(const T& t) {
m_data.push_back(t);
}
private:
std::vector<data_types> m_data;
};
int main()
{
Data d;
d.push_back(0);
d.push_back("string");
d.push_back(3.55);
}
I would like to access the values like d[0] (should return int) or d[1] (should return std::string).
What I have tried so far but what isn't working is to add the following public method to the existing struct:
template <class T>
T& operator[](const size_t &index) {
return std::visit([](const T& value) {
return static_cast<T>(value);
}, m_data[index]);
}
Any ideas how to achieve the desired result?
The type of an expression in C++ cannot depend on runtime parameters; basically it can only depend on types of the arguments, plus non-type template arguments.
So d[0] and d[1] must have the same type, as the type of the pieces of the expression are identical, and there are no non-type template arguments.
std::get<int>(d[0]) vs std::get<double>(d[1]) can differ in type.
std::get<1>(d[0]) vs std::get<2>(d[1]) can differ in type.
std::visit is a mechanism used to get around this; here, we create every a function object call, one for each possible type, and then pick one at runtime to actually call. However, the type returned from the visit still follows the above rule: it doesn't depend on what type is stored in the variant, and every possible type in the variant must have a valid instantiation of the function.
C++ type system is not a runtime type system. It is compile-time. Stuff like variant and dynamic_cast and any give some runtime exposure to it, but it is intentionally minimal.
If you are wanting to print the contents of a variant, you can do this:
std::visit([](auto& x){
std::cout << x;
}, d[0]);
the trick here is that each of the various types of variant have a lambda function body written for them (so they all must be valid). Then, at run time, the one actually in the variant is run.
You can also test the variant and ask if it has a specific type, either via std::get or manually.
bool has_int = std::visit([](auto& x){
return std::is_same_v<int, std::decay_t<decltype(x)>>::value;
}, d[0]);
this gives you a bool saying if d[0] has an int in it or not.
The next bit is getting insane. Please don't read this unless you fully understand how to use variants and want to know more:
You can even extract out the type index of the variant and pass that around as a run time value:
template<auto I>
using konstant_t = std::integral_constant<decltype(I),I>;
template<auto I>
constexpr konstant_t<I> konstant_v{};
template<auto...Is>
using venum_t = std::variant< konstant_t<Is>... >;
template<class Is>
struct make_venum_helper;
template<class Is>
using make_venum_helper_t = typename make_venum_helper<Is>::type;
template<std::size_t...Is>
struct make_venum_helper<std::index_sequence<Is...>>{
using type=venum_t<Is...>;
};
template<std::size_t N>
using make_venum_t = typename make_venum_helper<std::make_index_sequence<N>>::type;
template<std::size_t...Is>
constexpr auto venum_v( std::index_sequence<Is...>, std::size_t I ) {
using venum = make_venum_t<sizeof...(Is)>;
constexpr venum arr[]={
venum( konstant_v<Is> )...
};
return arr[I];
}
template<std::size_t N>
constexpr auto venum_v( std::size_t I ) {
return venum_v( std::make_index_sequence<N>{}, I );
}
template<class...Ts>
constexpr auto venum_v( std::variant<Ts...> const& v ) {
return venum_v< sizeof...(Ts) >( v.index() );
}
now you can do this:
using venum = make_venum_t<3>;
venum idx = venum_v(d[0]);
and idx holds the index of the engaged type in d[0]. This is only somewhat useful, as you still need std::visit to use it usefully:
std::visit([&](auto I) {
std::cout << std::get<I>( d[0] );
}, idx );
(within the lambda, I is a std::integral_constant, which can be constexpr converted to an integer.)
but lets you do some interesting things with it.
To extract a value from variant, use std::get:
struct Data
{
...
template <class T>
T& operator[](size_t index)
{
return std::get<T>(m_data[index]);
}
};
However, because this overloaded operator is a template, you can't use simple operator syntax to call it. Use the verbose syntax:
int main()
{
Data d;
d.push_back(0);
d.push_back("string");
d.push_back(3.55);
std::cout << d.operator[]<double>(2);
}
Or rename it to use a plain name instead of the fancy operator[].
Visitor pattern:
#include <iostream>
#include <string>
#include <variant>
#include <vector>
template <class ...Ts>
struct MultiVector : std::vector<std::variant<Ts...>> {
template <class Visitor>
void visit(std::size_t i, Visitor&& v) {
std::visit(v, (*this)[i]);
}
};
int main() {
MultiVector<std::string, int, double> vec;
vec.push_back(0);
vec.push_back("string");
vec.push_back(3.55);
vec.visit(2, [](auto& e) { std::cout << e << '\n'; });
}
The problem I'm trying to solve is to sort a template parameter pack according to the return value of a constexpr templated function specialized for each of the types I'm sorting.
I have a list of approximately 100 BOOST_STRONG_TYPEDEFs which creates types TYPE_1, TYPE_2, ..., TYPE_N.
BOOST_STRONG_TYPEDEF(TYPE_1, int)
BOOST_STRONG_TYPEDEF(TYPE_2, double)
// et cetera
BOOST_STRONG_TYPEDEF(TYPE_N, uint8_t)
Then I declare a general template constexpr size_t value_of() for which I specialize for each one of my types:
template<> constexpr size_t value_of<TYPE_1>() { return 1; }
template<> constexpr size_t value_of<TYPE_2>() { return 2; }
// et cetera
template<> constexpr size_t value_of<TYPE_N>() { return n; }
Then I have a class declared as follows. I need to sort each of the types in the UnsortedTypes parameter pack according to the result of value_of.
template<typename ...UnsortedTypes>
class MyClass {
typedef boost::mpl::vector<UnsortedTypes...> UnsortedTypeVector;
typedef typename boost::mpl::sort<
UnsortedTypeVector,
boost::mpl::less<
boost::mpl::size_t<value_of<boost::mpl::placeholders::_1>()>,
boost::mpl::size_t<value_of<boost::mpl::placeholders::_2>()>
>
>::type SortedTypes;
// Utility
void print_types() {
__print_types<SortedTypes>();
}
template<typename Type, typename ...Types>
void __print_types() {
std::cout << typeid(Type).name() << "\n";
if constexpr (sizeof...(Types) > 0) __print_types<Types...>();
}
};
When I test it out as follows:
int main(int, char *[]) {
MyClass<TYPE_5, TYPE_3, TYPE_4, TYPE_2, TYPE_1> myclass;
myclass.print_types();
}
I get this huge, pretty much unintelligible error message which seems to consist of errors within the mpl library.
Intuitively, I have a suspicion that this results from an incorrect definition of my sorting predicate. However, I'm not sure how to fix it!
(This is my first time using Boost.MPL and there aren't many examples online, so please be gentle!)
Here's a reduced example that might make it more obvious what's going on:
namespace mpl = boost::mpl;
template <typename T> constexpr size_t value_of() { return sizeof(T); }
template <typename... Ts>
struct X {
using V = mpl::vector<Ts...>;
using sorted = typename mpl::sort<
V,
mpl::less<
mpl::size_t<value_of<mpl::_1>()>,
// ~~~~~~~~~~~~~~~~~~~
mpl::size_t<value_of<mpl::_2>()>
>
>::type;
};
Now, you intended that this delays the invocation of value_of() until _1 is substituted into. But actually what happens is that it's invoked immediately - because that's what you're asking for. In my case, that's whatever sizeof(_1) ends up being. And so, since these are all constants, the full mpl::less<...> is just some integral constant expression - rather than being a lambda expression, like you wanted it to be.
What you need to do is ensure that invocation is delayed by turning your predicate into a metafunction:
template <typename T>
struct value_of_ : mpl::size_t<sizeof(T)> { };
And then you can use:
template <typename... Ts>
struct X {
using V = mpl::vector<Ts...>;
using sorted = typename mpl::sort<
V,
mpl::less<value_of_<mpl::_1>, value_of_<mpl::_2>>
>::type;
};
How can I use std::make_tuple if the execution order of the constructors is important?
For example I guess the execution order of the constructor of class A and the constructor of class B is undefined for:
std::tuple<A, B> t(std::make_tuple(A(std::cin), B(std::cin)));
I came to that conclusion after reading a comment to the question
Translating a std::tuple into a template parameter pack
that says that this
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
implementation has an undefined execution order of the constructors.
Update, providing some context:
To give some more background to what I am trying to do, here is a sketch:
I want to read in some serialized objects from stdin with the help of CodeSynthesis XSD binary parsing/serializing. Here is an example of how such parsing and serialization is done: example/cxx/tree/binary/xdr/driver.cxx
xml_schema::istream<XDR> ixdr (xdr);
std::auto_ptr<catalog> copy (new catalog (ixdr));
I want to be able to specify a list of the classes that the serialized objects have (e.g. catalog, catalog, someOtherSerializableClass for 3 serialized objects) and store that information as a typedef
template <typename... Args>
struct variadic_typedef {};
typedef variadic_typedef<catalog, catalog, someOtherSerializableClass> myTypes;
as suggested in Is it possible to “store” a template parameter pack without expanding it?
and find a way to get a std::tuple to work with after the parsing has finished. A sketch:
auto serializedObjects(binaryParse<myTypes>(std::cin));
where serializedObjects would have the type
std::tuple<catalog, catalog, someOtherSerializableClass>
The trivial solution is not to use std::make_tuple(...) in the first place but to construct a std::tuple<...> directly: The order in which constructors for the members are called is well defined:
template <typename>
std::istream& dummy(std::istream& in) {
return in;
}
template <typename... T>
std::tuple<T...> parse(std::istream& in) {
return std::tuple<T...>(dummy<T>(in)...);
}
The function template dummy<T>() is only used to have something to expand on. The order is imposed by construction order of the elements in the std::tuple<T...>:
template <typename... T>
template <typename... U>
std::tuple<T...>::tuple(U...&& arg)
: members_(std::forward<U>(arg)...) { // NOTE: pseudo code - the real code is
} // somewhat more complex
Following the discussion below and Xeo's comment it seems that a better alternative is to use
template <typename... T>
std::tuple<T...> parse(std::istream& in) {
return std::tuple<T...>{ T(in)... };
}
The use of brace initialization works because the order of evaluation of the arguments in a brace initializer list is the order in which they appear. The semantics of T{...} are described in 12.6.1 [class.explicit.init] paragraph 2 stating that it follows the rules of list initialization semantics (note: this has nothing to do with std::initializer_list which only works with homogenous types). The ordering constraint is in 8.5.4 [dcl.init.list] paragraph 4.
As the comment says, you could just use initializer-list:
return std::tuple<args...>{args(stream)...};
which will work for std::tuple and suchlikes (which supports initializer-list).
But I got another solution which is more generic, and can be useful where initializer-list cannot be used. So lets solve this without using initializer-list:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
Before I explain my solution, I would like to discuss the problem first. In fact, thinking about the problem step by step would also help us to come up with a solution eventually. So, to simply the discussion (and thinking-process), lets assume that args expands to 3 distinct types viz. X, Y, Z, i.e args = {X, Y, Z} and then we can think along these lines, reaching towards the solution step-by-step:
First and foremost, the constructors of X, Y, and Z can be executed in any order, because the order in which function arguments are evaluated is unspecified by the C++ Standard.
But we want X to construct first, then Y, and Z. Or at least we want to simulate that behavior, which means X must be constructed with data that is in the beginning of the input stream (say that data is xData) and Y must be constructed with data that comes immediately after xData, and so on.
As we know, X is not guaranteed to be constructed first, so we need to pretend. Basically, we will read the data from the stream as if it is in the beginning of the stream, even if Z is constructed first, that seems impossible. It is impossible as long as we read from the input stream, but we read data from some indexable data structure such as std::vector, then it is possible.
So my solution does this: it will populate a std::vector first, and then all arguments will read data from this vector.
My solution assumes that each line in the stream contains all the data needed to construct an object of any type.
Code:
//PARSE FUNCTION
template<typename... args>
std::tuple<args...> parse(std::istream &stream)
{
const int N = sizeof...(args);
return tuple_maker<args...>().make(stream, typename genseq<N>::type() );
}
And tuple_maker is defined as:
//FRAMEWORK - HELPER ETC
template<int ...>
struct seq {};
template<int M, int ...N>
struct genseq : genseq<M-1,M-1, N...> {};
template<int ...N>
struct genseq<0,N...>
{
typedef seq<N...> type;
};
template<typename...args>
struct tuple_maker
{
template<int ...N>
std::tuple<args...> make(std::istream & stream, const seq<N...> &)
{
return std::make_tuple(args(read_arg<N>(stream))...);
}
std::vector<std::string> m_params;
std::vector<std::unique_ptr<std::stringstream>> m_streams;
template<int Index>
std::stringstream & read_arg(std::istream & stream)
{
if ( m_params.empty() )
{
std::string line;
while ( std::getline(stream, line) ) //read all at once!
{
m_params.push_back(line);
}
}
auto pstream = new std::stringstream(m_params.at(Index));
m_streams.push_back(std::unique_ptr<std::stringstream>(pstream));
return *pstream;
}
};
TEST CODE
///TEST CODE
template<int N>
struct A
{
std::string data;
A(std::istream & stream)
{
stream >> data;
}
friend std::ostream& operator << (std::ostream & out, A<N> const & a)
{
return out << "A" << N << "::data = " << a.data ;
}
};
//three distinct classes!
typedef A<1> A1;
typedef A<2> A2;
typedef A<3> A3;
int main()
{
std::stringstream ss("A1\nA2\nA3\n");
auto tuple = parse<A1,A2,A3>(ss);
std::cout << std::get<0>(tuple) << std::endl;
std::cout << std::get<1>(tuple) << std::endl;
std::cout << std::get<2>(tuple) << std::endl;
}
Output:
A1::data = A1
A2::data = A2
A3::data = A3
which is expected. See demo at ideone yourself. :-)
Note that this solution avoids the order-of-reading-from-the-stream problem by reading all the lines in the first call to read_arg itself, and all the later calls just read from the std::vector, using the index.
Now you can put some printf in the constructor of the classes, just to see that the order of construction is not same as the order of template arguments to the parse function template, which is interesting. Also, the technique used here can be useful for places where list-initialization cannot be used.
There's nothing special about make_tuple here. Any function call in C++ allows its arguments to be called in an unspecified order (allowing the compiler freedom to optimize).
I really don't suggest having constructors that have side-effects such that the order is important (this will be a maintenance nightmare), but if you absolutely need this, you can always construct the objects explicitly to set the order you want:
A a(std::cin);
std::tuple<A, B> t(std::make_tuple(a, B(std::cin)));
This answer comes from a comment I made to the template pack question
Since make_tuple deduces the tuple type from the constructed components and function arguments have undefined evaluation ordder, the construction has to happen inside the machinery, which is what I proposed in the comment. In that case, there's no need to use make_tuple; you could construct the tuple directly from the tuple type. But that doesn't order construction either; what I do here is construct each component of the tuple, and then build a tuple of references to the components. The tuple of references can be easily converted to a tuple of the desired type, provided the components are easy to move or copy.
Here's the solution (from the lws link in the comment) slightly modified, and explained a bit. This version only handles tuples whose types are all different, but it's easier to understand; there's another version below which does it correctly. As with the original, the tuple components are all given the same constructor argument, but changing that simply requires adding a ... to the lines indicated with // Note: ...
#include <tuple>
#include <type_traits>
template<typename...T> struct ConstructTuple {
// For convenience, the resulting tuple type
using type = std::tuple<T...>;
// And the tuple of references type
using ref_type = std::tuple<T&...>;
// Wrap each component in a struct which will be used to construct the component
// and hold its value.
template<typename U> struct Wrapper {
U value;
template<typename Arg>
Wrapper(Arg&& arg)
: value(std::forward<Arg>(arg)) {
}
};
// The implementation class derives from all of the Wrappers.
// C++ guarantees that base classes are constructed in order, and
// Wrappers are listed in the specified order because parameter packs don't
// reorder.
struct Impl : Wrapper<T>... {
template<typename Arg> Impl(Arg&& arg) // Note ...Arg, ...arg
: Wrapper<T>(std::forward<Arg>(arg))... {}
};
template<typename Arg> ConstructTuple(Arg&& arg) // Note ...Arg, ...arg
: impl(std::forward<Arg>(arg)), // Note ...
value((static_cast<Wrapper<T>&>(impl)).value...) {
}
operator type() const { return value; }
ref_type operator()() const { return value; }
Impl impl;
ref_type value;
};
// Finally, a convenience alias in case we want to give `ConstructTuple`
// a tuple type instead of a list of types:
template<typename Tuple> struct ConstructFromTupleHelper;
template<typename...T> struct ConstructFromTupleHelper<std::tuple<T...>> {
using type = ConstructTuple<T...>;
};
template<typename Tuple>
using ConstructFromTuple = typename ConstructFromTupleHelper<Tuple>::type;
Let's take it for a spin
#include <iostream>
// Three classes with constructors
struct Hello { char n; Hello(decltype(n) n) : n(n) { std::cout << "Hello, "; }; };
struct World { double n; World(decltype(n) n) : n(n) { std::cout << "world"; }; };
struct Bang { int n; Bang(decltype(n) n) : n(n) { std::cout << "!\n"; }; };
std::ostream& operator<<(std::ostream& out, const Hello& g) { return out << g.n; }
std::ostream& operator<<(std::ostream& out, const World& g) { return out << g.n; }
std::ostream& operator<<(std::ostream& out, const Bang& g) { return out << g.n; }
using std::get;
using Greeting = std::tuple<Hello, World, Bang>;
std::ostream& operator<<(std::ostream& out, const Greeting &n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
// Constructors run in order
Greeting greet = ConstructFromTuple<Greeting>(33.14159);
// Now show the result
std::cout << greet << std::endl;
return 0;
}
See it in action on liveworkspace. Verify that it constructs in the same order in both clang and gcc (libc++'s tuple implementation holds tuple components in the reverse order to stdlibc++, so it's a reasonable test, I guess.)
To make this work with tuples which might have more than one of the same component, it's necessary to modify Wrapper to be a unique struct for each component. The easiest way to do this is to add a second template parameter, which is a sequential index (both libc++ and libstdc++ do this in their tuple implementations; it's a standard technique). It would be handy to have the "indices" implementation kicking around to do this, but for exposition purposes, I've just done a quick-and-dirty recursion:
#include <tuple>
#include <type_traits>
template<typename T, int I> struct Item {
using type = T;
static const int value = I;
};
template<typename...TI> struct ConstructTupleI;
template<typename...T, int...I> struct ConstructTupleI<Item<T, I>...> {
using type = std::tuple<T...>;
using ref_type = std::tuple<T&...>;
// I is just to distinguish different wrappers from each other
template<typename U, int J> struct Wrapper {
U value;
template<typename Arg>
Wrapper(Arg&& arg)
: value(std::forward<Arg>(arg)) {
}
};
struct Impl : Wrapper<T, I>... {
template<typename Arg> Impl(Arg&& arg)
: Wrapper<T, I>(std::forward<Arg>(arg))... {}
};
template<typename Arg> ConstructTupleI(Arg&& arg)
: impl(std::forward<Arg>(arg)),
value((static_cast<Wrapper<T, I>&>(impl)).value...) {
}
operator type() const { return value; }
ref_type operator()() const { return value; }
Impl impl;
ref_type value;
};
template<typename...T> struct List{};
template<typename L, typename...T> struct WrapNum;
template<typename...TI> struct WrapNum<List<TI...>> {
using type = ConstructTupleI<TI...>;
};
template<typename...TI, typename T, typename...Rest>
struct WrapNum<List<TI...>, T, Rest...>
: WrapNum<List<TI..., Item<T, sizeof...(TI)>>, Rest...> {
};
// Use WrapNum to make ConstructTupleI from ConstructTuple
template<typename...T> using ConstructTuple = typename WrapNum<List<>, T...>::type;
// Finally, a convenience alias in case we want to give `ConstructTuple`
// a tuple type instead of a list of types:
template<typename Tuple> struct ConstructFromTupleHelper;
template<typename...T> struct ConstructFromTupleHelper<std::tuple<T...>> {
using type = ConstructTuple<T...>;
};
template<typename Tuple>
using ConstructFromTuple = typename ConstructFromTupleHelper<Tuple>::type;
With test here.
I believe the only way to manually unroll the definition. Something like the following might work. I welcome attempts to make it nicer though.
#include <iostream>
#include <tuple>
struct A { A(std::istream& is) {}};
struct B { B(std::istream& is) {}};
template <typename... Ts>
class Parser
{ };
template <typename T>
class Parser<T>
{
public:
static std::tuple<T> parse(std::istream& is) {return std::make_tuple(T(is)); }
};
template <typename T, typename... Ts>
class Parser<T, Ts...>
{
public:
static std::tuple<T,Ts...> parse(std::istream& is)
{
A t(is);
return std::tuple_cat(std::tuple<T>(std::move(t)),
Parser<Ts...>::parse(is));
}
};
int main()
{
Parser<A,B>::parse(std::cin);
return 1;
}
Forgive me if this has been answered already, as I couldn't find it...
Basically I have an object that needs to take a variadic argument list in it's constructor and store the arguments in a vector. How do I initialize a vector from a the arguments of a variadic constructor?
class GenericNode {
public:
GenericNode(GenericNode*... inputs) {
/* Something like... */
// inputs_.push_back(inputs)...;
}
private:
std::vector<GenericNode*> inputs_;
};
The best thing would be to use an initializer list
#include <initializer_list>
#include <vector>
class GenericNode {
public:
GenericNode(std::initializer_list<GenericNode*> inputs)
:inputs_(inputs) {} //well that's easy
private:
std::vector<GenericNode*> inputs_;
};
int main() {
GenericNode* ptr;
GenericNode node{ptr, ptr, ptr, ptr};
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c
The closest to what you already have, using C++11 is to use the vector's initializer_list:
template<class ...Ts>
GenericNode(Ts... inputs)
:inputs_{inputs...} {} //well that's easy too
//compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae
And here's a C++11 version with no initializer_lists at all. It's ugly, and complicated, and requires features missing from many compilers. Use the initializer list
template<class T>
using Alias = T;
class GenericNode {
public:
template<class ...Ts>
GenericNode(Ts... inputs) { //SFINAE might be appropriate
using ptr = GenericNode*;
Alias<char[]>{( //first part of magic unpacker
inputs_.push_back(ptr(inputs))
,'0')...,'0'}; //second part of magic unpacker
}
private:
std::vector<GenericNode*> inputs_;
};
int main() {
GenericNode* ptr;
GenericNode node(ptr, ptr, ptr, ptr);
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//thanks to R. Martinho Fernandes for helping me get it to compile
Unrelated to everything, I don't know if those are owning pointers or not. If they are, use std::unique_ptr instead.
// inputs_.push_back(inputs)...;
This doesn't work because you can't expand a parameter pack as a statement, only in certain contexts such as a function argument list or initializer-list.
Also your constructor signature is wrong, if you're trying to write a variadic template it needs to be a template!
Once you write your constructor signature correctly the answer is easy, just construct the vector with the pack expansion:
#include <vector>
class GenericNode
{
public:
template<typename... T>
GenericNode(T*... inputs) : inputs_{ inputs... }
{ }
private:
std::vector<GenericNode*> inputs_;
};
(You could instead have set it in the constructor body with:
inputs_ = { inputs... };
but the cool kids use member initializers not assignment in the constructor body.)
The downside of this solution is that the template constructor accepts any type of pointer arguments, but will then give an error when trying to construct the vector if the arguments aren't convertible to GenericNode*. You could constrain the template to only accept GenericNode pointers, but that's what happens automatically if you do what the other answers suggest and make the constructor take a std::initializer_list<GenericNode*>, and then you don't need any ugly enable_if SFINAE tricks.
You can't use a variadic argument list unless it's a template, you can, as stated, use a initializer_list like this:
class GenericNode {
public:
GenericNode(std::initializer_list<GenericNode*> inputs) : inputs_(inputs)
{
}
private:
std::vector<GenericNode*> inputs_;
};
template <class ... T>
GenericNode* foo(T ... t)
{
return new GenericNode({t...});
}
class Blob
{
std::vector<std::string> _v;
public:
template<typename... Args>
Blob(Args&&... args)
: _v(std::forward<Args>(args)...)
{ }
};
int main(void)
{
const char * shapes[3] = { "Circle", "Triangle", "Square" };
Blob b1(5, "C++ Truths");
Blob b2(shapes, shapes+3);
}
Example from C++11 Truths looks simple enough...;)
Not a complete solution but might give you some ideas.
Another way to do it:
#include <iostream>
#include <vector>
using std::vector;
template <typename T>
void variadic_vector_emplace(vector<T>&) {}
template <typename T, typename First, typename... Args>
void variadic_vector_emplace(vector<T>& v, First&& first, Args&&... args)
{
v.emplace_back(std::forward<First>(first));
variadic_vector_emplace(v, std::forward<Args>(args)...);
}
struct my_struct
{
template <typename... Args>
my_struct(Args&&... args)
{
variadic_vector_emplace(_data, std::forward<Args>(args)...);
}
vector<int>& data() { return _data; }
private:
vector<int> _data;
};
int main()
{
my_struct my(5, 6, 7, 8);
for(int i : my.data())
std::cout << i << std::endl;
}
I recently wrote the following function that takes a string with
{1} , {2} , {3} ... in it and substitutes the argument list. I ran in to the same problem until I decided to let the compiler work it out for itself with the auto keyword.
#include <string>
#include <vector>
using std::string;
using std::vector;
template<typename S, typename... Args>
string interpolate( const S& orig , const Args&... args)
{
string out(orig);
auto va = {args...};
vector<string> v{va};
size_t i = 1;
for( string s: v)
{
string is = std::to_string(i);
string t = "{" + is + "}";
try
{
auto pos = out.find(t);
if(pos != out.npos)
{
out.erase(pos, t.length());
out.insert( pos, s);
}
i++;
}
catch( std::exception& e)
{
std::cerr << e.what() << std::endl;
}
} // for
return out;
}
Apparently that is good enough as long as the types line up correctly.
In this case I am using only std::string throughout.
I think this is an elegant technique, but it may have drawbacks.
Note: If the element-type of a vector is not copy-initializable (it is in OP post), the std::initializer list route will not work.
You can still use a variadic unpack statement (post C++ 17):
(inputs_.emplace_back(std::move(args)), ...);
I'm trying to find a method to iterate over an a pack variadic template argument list.
Now as with all iterations, you need some sort of method of knowing how many arguments are in the packed list, and more importantly how to individually get data from a packed argument list.
The general idea is to iterate over the list, store all data of type int into a vector, store all data of type char* into a vector, and store all data of type float, into a vector. During this process there also needs to be a seperate vector that stores individual chars of what order the arguments went in. As an example, when you push_back(a_float), you're also doing a push_back('f') which is simply storing an individual char to know the order of the data. I could also use a std::string here and simply use +=. The vector was just used as an example.
Now the way the thing is designed is the function itself is constructed using a macro, despite the evil intentions, it's required, as this is an experiment. So it's literally impossible to use a recursive call, since the actual implementation that will house all this will be expanded at compile time; and you cannot recruse a macro.
Despite all possible attempts, I'm still stuck at figuring out how to actually do this. So instead I'm using a more convoluted method that involves constructing a type, and passing that type into the varadic template, expanding it inside a vector and then simply iterating that. However I do not want to have to call the function like:
foo(arg(1), arg(2.0f), arg("three");
So the real question is how can I do without such? To give you guys a better understanding of what the code is actually doing, I've pasted the optimistic approach that I'm currently using.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& t) { return t.FLOAT; } };
template<> struct get<char*> { char* operator()(const any& t) { return t.STRING; } };
#define def(name) \
template<typename... T> \
auto name (T... argv) -> any { \
std::initializer_list<any> argin = { argv... }; \
std::vector<any> args = argin;
#define get(name,T) get<T>()(args[name])
#define end }
any arg(int a) { any arg; arg.INT = a; return arg; }
any arg(float f) { any arg; arg.FLOAT = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }
I know this is nasty, however it's a pure experiment, and will not be used in production code. It's purely an idea. It could probably be done a better way. But an example of how you would use this system:
def(foo)
int data = get(0, int);
std::cout << data << std::endl;
end
looks a lot like python. it works too, but the only problem is how you call this function.
Heres a quick example:
foo(arg(1000));
I'm required to construct a new any type, which is highly aesthetic, but thats not to say those macros are not either. Aside the point, I just want to the option of doing:
foo(1000);
I know it can be done, I just need some sort of iteration method, or more importantly some std::get method for packed variadic template argument lists. Which I'm sure can be done.
Also to note, I'm well aware that this is not exactly type friendly, as I'm only supporting int,float,char* and thats okay with me. I'm not requiring anything else, and I'll add checks to use type_traits to validate that the arguments passed are indeed the correct ones to produce a compile time error if data is incorrect. This is purely not an issue. I also don't need support for anything other then these POD types.
It would be highly apprecaited if I could get some constructive help, opposed to arguments about my purely illogical and stupid use of macros and POD only types. I'm well aware of how fragile and broken the code is. This is merley an experiment, and I can later rectify issues with non-POD data, and make it more type-safe and useable.
Thanks for your undertstanding, and I'm looking forward to help.
If your inputs are all of the same type, see OMGtechy's great answer.
For mixed-types we can use fold expressions (introduced in c++17) with a callable (in this case, a lambda):
#include <iostream>
template <class ... Ts>
void Foo (Ts && ... inputs)
{
int i = 0;
([&]
{
// Do things in your "loop" lambda
++i;
std::cout << "input " << i << " = " << inputs << std::endl;
} (), ...);
}
int main ()
{
Foo(2, 3, 4u, (int64_t) 9, 'a', 2.3);
}
Live demo
(Thanks to glades for pointing out in the comments that I didn't need to explicitly pass inputs to the lambda. This made it a lot neater.)
If you need return/breaks in your loop, here are some workarounds:
Demo using try/throw. Note that throws can cause tremendous slow down of this function; so only use this option if speed isn't important, or the break/returns are genuinely exceptional.
Demo using variable/if switches.
These latter answers are honestly a code smell, but shows it's general-purpose.
If you want to wrap arguments to any, you can use the following setup. I also made the any class a bit more usable, although it isn't technically an any class.
#include <vector>
#include <iostream>
struct any {
enum type {Int, Float, String};
any(int e) { m_data.INT = e; m_type = Int;}
any(float e) { m_data.FLOAT = e; m_type = Float;}
any(char* e) { m_data.STRING = e; m_type = String;}
type get_type() const { return m_type; }
int get_int() const { return m_data.INT; }
float get_float() const { return m_data.FLOAT; }
char* get_string() const { return m_data.STRING; }
private:
type m_type;
union {
int INT;
float FLOAT;
char *STRING;
} m_data;
};
template <class ...Args>
void foo_imp(const Args&... args)
{
std::vector<any> vec = {args...};
for (unsigned i = 0; i < vec.size(); ++i) {
switch (vec[i].get_type()) {
case any::Int: std::cout << vec[i].get_int() << '\n'; break;
case any::Float: std::cout << vec[i].get_float() << '\n'; break;
case any::String: std::cout << vec[i].get_string() << '\n'; break;
}
}
}
template <class ...Args>
void foo(Args... args)
{
foo_imp(any(args)...); //pass each arg to any constructor, and call foo_imp with resulting any objects
}
int main()
{
char s[] = "Hello";
foo(1, 3.4f, s);
}
It is however possible to write functions to access the nth argument in a variadic template function and to apply a function to each argument, which might be a better way of doing whatever you want to achieve.
Range based for loops are wonderful:
#include <iostream>
#include <any>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p.type().name() << std::endl;
}
}
int main() {
printVariadic(std::any(42), std::any('?'), std::any("C++"));
}
For me, this produces the output:
i
c
PKc
Here's an example without std::any, which might be easier to understand for those not familiar with std::type_info:
#include <iostream>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p << std::endl;
}
}
int main() {
printVariadic(1, 2, 3);
}
As you might expect, this produces:
1
2
3
You can create a container of it by initializing it with your parameter pack between {}. As long as the type of params... is homogeneous or at least convertable to the element type of your container, it will work. (tested with g++ 4.6.1)
#include <array>
template <class... Params>
void f(Params... params) {
std::array<int, sizeof...(params)> list = {params...};
}
This is not how one would typically use Variadic templates, not at all.
Iterations over a variadic pack is not possible, as per the language rules, so you need to turn toward recursion.
class Stock
{
public:
bool isInt(size_t i) { return _indexes.at(i).first == Int; }
int getInt(size_t i) { assert(isInt(i)); return _ints.at(_indexes.at(i).second); }
// push (a)
template <typename... Args>
void push(int i, Args... args) {
_indexes.push_back(std::make_pair(Int, _ints.size()));
_ints.push_back(i);
this->push(args...);
}
// push (b)
template <typename... Args>
void push(float f, Args... args) {
_indexes.push_back(std::make_pair(Float, _floats.size()));
_floats.push_back(f);
this->push(args...);
}
private:
// push (c)
void push() {}
enum Type { Int, Float; };
typedef size_t Index;
std::vector<std::pair<Type,Index>> _indexes;
std::vector<int> _ints;
std::vector<float> _floats;
};
Example (in action), suppose we have Stock stock;:
stock.push(1, 3.2f, 4, 5, 4.2f); is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(3.2f, 4, 5, 4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push(4, 5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push();, which is resolved to (c) as there is no argument, thus ending the recursion
Thus:
Adding another type to handle is as simple as adding another overload, changing the first type (for example, std::string const&)
If a completely different type is passed (say Foo), then no overload can be selected, resulting in a compile-time error.
One caveat: Automatic conversion means a double would select overload (b) and a short would select overload (a). If this is not desired, then SFINAE need be introduced which makes the method slightly more complicated (well, their signatures at least), example:
template <typename T, typename... Args>
typename std::enable_if<is_int<T>::value>::type push(T i, Args... args);
Where is_int would be something like:
template <typename T> struct is_int { static bool constexpr value = false; };
template <> struct is_int<int> { static bool constexpr value = true; };
Another alternative, though, would be to consider a variant type. For example:
typedef boost::variant<int, float, std::string> Variant;
It exists already, with all utilities, it can be stored in a vector, copied, etc... and seems really much like what you need, even though it does not use Variadic Templates.
There is no specific feature for it right now but there are some workarounds you can use.
Using initialization list
One workaround uses the fact, that subexpressions of initialization lists are evaluated in order. int a[] = {get1(), get2()} will execute get1 before executing get2. Maybe fold expressions will come handy for similar techniques in the future. To call do() on every argument, you can do something like this:
template <class... Args>
void doSomething(Args... args) {
int x[] = {args.do()...};
}
However, this will only work when do() is returning an int. You can use the comma operator to support operations which do not return a proper value.
template <class... Args>
void doSomething(Args... args) {
int x[] = {(args.do(), 0)...};
}
To do more complex things, you can put them in another function:
template <class Arg>
void process(Arg arg, int &someOtherData) {
// You can do something with arg here.
}
template <class... Args>
void doSomething(Args... args) {
int someOtherData;
int x[] = {(process(args, someOtherData), 0)...};
}
Note that with generic lambdas (C++14), you can define a function to do this boilerplate for you.
template <class F, class... Args>
void do_for(F f, Args... args) {
int x[] = {(f(args), 0)...};
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
Using recursion
Another possibility is to use recursion. Here is a small example that defines a similar function do_for as above.
template <class F, class First, class... Rest>
void do_for(F f, First first, Rest... rest) {
f(first);
do_for(f, rest...);
}
template <class F>
void do_for(F f) {
// Parameter pack is empty.
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
You can't iterate, but you can recurse over the list. Check the printf() example on wikipedia: http://en.wikipedia.org/wiki/C++0x#Variadic_templates
You can use multiple variadic templates, this is a bit messy, but it works and is easy to understand.
You simply have a function with the variadic template like so:
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
And a helper function like so:
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
Now when you call "function" the "helperFunction" will be called and isolate the first passed parameter from the rest, this variable can b used to call another function (or something). Then "function" will be called again and again until there are no more variables left. Note you might have to declare helperClass before "function".
The final code will look like this:
void helperFunction();
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args);
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
The code is not tested.
#include <iostream>
template <typename Fun>
void iteratePack(const Fun&) {}
template <typename Fun, typename Arg, typename ... Args>
void iteratePack(const Fun &fun, Arg &&arg, Args&& ... args)
{
fun(std::forward<Arg>(arg));
iteratePack(fun, std::forward<Args>(args)...);
}
template <typename ... Args>
void test(const Args& ... args)
{
iteratePack([&](auto &arg)
{
std::cout << arg << std::endl;
},
args...);
}
int main()
{
test(20, "hello", 40);
return 0;
}
Output:
20
hello
40