Constructor and functions using variadic templated parameters - c++

I want to write a class which is templated by a number of dimensions:
namespace detail {
enum class enabler {};
}
template<size_t dim>
class templateClass
{
public:
template<class... DimArgs, typename std::enable_if<sizeof...(DimArgs)==dim, detail::enabler>::type...>
templateClass(DimArgs... dimensions) {
// Use integers passed to the constructor, one for each dimension
}
};
The detail::enabler enum is found at this almost-static-if link. Here it is used as a second parameter pack, allowing 0 arguments to be passed. The scoped enum has no members, and can't(?) be accidentally passed.
They also use a using declaration to swallow some of the typename etc parts up, but I've typed in full to avoid having to read it there.
How can I use the dimensions parameter pack that I've passed?
The class works well, eg:
templateClass<2> temp(5, 2); // works
templateClass<3> temp(5, 2, 4); // works
templateClass<1> temp(5,2); // would give compile-time error
but perhaps I've gotten a (or several) bad idea(s) of what I should use/do here?
Edit:
One solution I've found is to create a std::initializer_list. I can create this with an int or size_t class, which works nicely here. However, if I don't know the type of the arguments being passed (for example, because my function can take both ints and doubles, for some other purpose), is there a better way than:
std::initializer_list<int> list{dimensions...};
for (int i : list) {
std::cout << "i = " << i << std::endl;
}
Full working example:
Mesh.H:
#ifndef MESH_H
#define MESH_H
#include <type_traits>
#include <initializer_list>
#include <iostream>
namespace detail {
enum class enabler {};
}
template <bool Condition>
using EnableIf =
typename std::enable_if<Condition, detail::enabler>::type;
template<size_t meshDim>
class Mesh
{
public:
template<class... DimArgs, EnableIf<sizeof...(DimArgs)==meshDim>...>
Mesh(DimArgs... dimensions){
std::initializer_list<int> list{dimensions...};
for (int i : list) {
std::cout << "i = " << i << std::endl;
}
}
};
#endif // MESH_H
main.cpp:
#include <iostream>
#include "Mesh.H"
int main()
{
Mesh<2> mesh(5, 2);
return 0;
}
Compiles with g++ --std=c++11 main.cpp

It's possible to index the parameter pack by putting it in a tuple:
using T1 = std::tuple_element<0, std::tuple<DimArgs...>>; // Any index should work, not just 0
That doesn't quite solve the issue of possible numeric promotion or narrowing, though. I'm thinking something that amounts to decltype(tuple_sum(dimensions...)) would do the trick (provided you can assume they're numeric). It could look something like this (untested):
template<typename T>
constexpr T tuple_sum(T n) {return n;}
template<typename T, typename... Rest>
constexpr auto tuple_sum(T first, Rest... rest) {
return first + tuple_sum(rest...);
}

To make the code portable you should not have the anonymous template parameter.
Here's code that compiles with MinGW g++ 5.1 and Visual C++ 2015:
#include <utility> // std::enable_if
#define IS_UNUSED( a ) (void) a; struct a
template< int dim >
class Tensor
{
public:
template< class... Args
, class Enabled_ = typename std::enable_if< sizeof...(Args) == dim, void >::type
>
Tensor( Args... args )
{
int const dimensions[] = { args... };
IS_UNUSED( dimensions );
}
};
auto main() -> int
{
Tensor<2> tempA(5, 2); // works
Tensor<3> tempB(5, 2, 4); // works
#ifdef FAIL
Tensor<1> temp(5,2); // would give compile-time error
#endif
}

Related

C++20 source_location to replace macro to multi-parameter variadic template

Can this be made to display the line number of the actual call site, like the macro does ?
#include <iostream>
#include <type_traits>
#include <source_location>
#include <cassert>
using namespace std;
namespace myLib{
template<typename Enumt, typename... Ts> // alert bad calls, throw
constexpr void setValsF(const unsigned line, Ts const&... args){
cout << "line #"<<line<<": illegal call to setVals()\n";
assert(is_enum_v<Enumt>);
}
template<class... Enumt, class = common_type_t<Enumt...> >
requires conjunction_v<is_enum<Enumt>...>
constexpr void setValsF(const unsigned line, Enumt&... vals){
cout << "line #"<<line<<": legal call to setVals()\n";
}
}// myLib
int main(){
enum enumVals : short { a = 0, b, c, count };
// #define setVals(...) myLib::setValsF<enumVals>(__LINE__ __VA_OPT__(,__VA_ARGS__))
constexpr auto setVals = [](auto&&... args) {
myLib::setValsF<enumVals>(source_location::current().line(), args...); };
setVals(a,b); // legal
setVals(b,"text"); // illegal
}
run
.. keeping a nice simple API ( setVals(a,b) ), that is.
It would work :
with a defaulted argument to the function template, but for the parameter pack. Couldn't figure a deduction guide in the presence of more than one template parameter.
or if current() was the default constructor to source_location !
I resorted to runtime handling of bad calls (to certain APIs) as a courtesy to my library users, as my very specific insult is wayyy nicer than the indecipherable blob the compiler vomits.
Expanding on my comment, as requested by the OP.
Piotr Skotnicki's accepted answer to How to use source_location in a variadic template function? introduces an helper class and a deduction guide:
template <typename... Ts>
struct debug
{
debug( Ts&&... ts
, const std::source_location& loc = >std::source_location::current());
};
// The deduction guide forces the deduction of the pack, "separating"
// it from the default parameter.
template <typename... Ts>
debug(Ts&&...) -> debug<Ts...>;
int main()
{
debug(5, 'A', 3.14f, "foo");
}
Here, though, something else needs to be passed. My proposal is to inject the requirements as a template parameter before the pack.
#include <concepts>
#include <iostream>
#include <source_location>
template <typename R, typename... Ts>
struct debug
{
debug( R&& req // <- A requirement that the pack ts must fulfill.
, Ts&&... ts
, std::source_location const& loc = std::source_location::current() )
{
std::cout << "line #" << loc.line() << ": "
<< ( req(ts...) ? "valid call\n" : "invalid call\n" );
}
};
// We don't need to differentiate the first parameter of the pack, here.
template <typename... Args>
debug(Args&&...) -> debug<Args...>;
int main()
{
enum enumVals : short { a = 0, b, c, count };
// Since C++20 we can have templated lambdas. Here I don't need named parameters,
// but I need named types to use std::same_as in the fold expression.
constexpr auto all_enums = []<typename... Ts>(Ts&&...) {
return ( ... and std::same_as<std::remove_cvref_t<Ts>, enumVals> );
};
debug(all_enums, a, b); // -> line #31: valid call
debug(all_enums, b, 1); // -> line #32: invalid call
}
This is not as terse as setVals(a,b), in OP's code, but seems to work1 as intended.
1) Note that this works with gcc and clang(trunk) (as noted by Ted Lyngmo), but not with clang15: https://godbolt.org/z/zxxMTs4Kj

Avoid if-else branching in string to type dispatching

Usually when you write a CLI tool which accepts parameter you have to deal with them. Most of the time you want to switch between behaviours based on the value of an argument.
The following is a common use case, where the program accepts a type and then prints something based on that type. I am using Boost to pre-process and auto generate the whole if-else branches.
This is very nice in terms of maintainability as I only need to update a define when I introduce a new type. On the other hand it is quite far from being modern and elegant.
I thought about using better-enums to avoid using the if-else to convert from string into an enum using the _from_string utility function. But then the way to go from enum to a type is still obscure to me.
Any suggestion on how to keep the nice maintainability of the current implementation but avoid to use pre-processor and macro functionalities?
#include <iostream>
#include <cstdlib>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <type_traits>
using a_type = int;
using b_type = long;
using c_type = float;
using d_type = double;
#define TYPES (a)(b)(c)(d)
template<typename T>
void foo(){
T num = 1;
std::cout << typeid(decltype(num)).name() << " : "<< num << std::endl;
};
int main(int argc, char **argv)
{
if (argc < 1) {
return 1;
}
std::string type = argv[1];
if (false) {
#define LOOP_BODY(R, DATA, T) \
} \
else if (type == BOOST_PP_STRINGIZE(T)) { \
foo<BOOST_PP_CAT(T, _type)>(); \
BOOST_PP_SEQ_FOR_EACH(LOOP_BODY, _, TYPES);
#undef LOOP_BODY
} else {
std::cout << "ERROR: Unknown type " << type << std::endl;
}
}
Working example at https://wandbox.org/permlink/60bAwoqYxzU1EUdw
Another way is to use a plain array and std::find_if instead of if-else:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <typeinfo>
struct Handler {
char const* name;
void(*fn)(std::string const&); // Or std::function<> to accept lambdas.
};
struct A {};
struct B {};
template<class T>
void foo(std::string const& name) {
std::cout << "foo<" << typeid(T).name() << ">: " << name << '\n';
}
int main(int, char** av) {
Handler const handlers[] = {
{"a", foo<A>}
, {"b", foo<B>}
};
std::string const name = av[1];
auto handler = std::find_if(std::begin(handlers), std::end(handlers), [&name](auto const& h) {
return name == h.name;
});
if(handler != std::end(handlers))
handler->fn(name);
}
You don't need to use the preprocessor to store an arbitrary list of types and generate code for them. We can use variadic templates and compile-time strings. You can isolate preprocessor usage to the generation of pairs of names and types.
Firstly, let's define a wrapper for a compile-time sequence of characters. Note that the use of the _cs literal is non-Standard, but available in every major compiler and likely to be part of C++20:
template <char... Cs>
using ct_str = std::integer_sequence<char, Cs...>;
template <typename T, T... Cs>
constexpr ct_str<Cs...> operator""_cs() { return {}; }
We can then define an empty type that stores a pair of a name and a type:
template <typename Name, typename T>
struct named_type
{
using name = Name;
using type = T;
};
And a macro to conveniently instantiate it:
#define NAMED_TYPE(type) \
named_type<decltype(#type ## _cs), type>
You can now use an empty variadic template class to store your types:
template <typename... Ts>
struct named_type_list { };
using my_types = named_type_list<
NAMED_TYPE(int),
NAMED_TYPE(long),
NAMED_TYPE(float),
NAMED_TYPE(double)
>;
Now, let's see how our main should look:
int main()
{
const std::string input{"float"};
handle(my_types{}, input, [](auto t)
{
print(typename decltype(t)::name{});
});
}
The above will print out "float". We can implement handle by unpacking the list of named_type types and using a fold expression to find the matching type name:
template <typename... Ts, typename F>
void handle(named_type_list<Ts...>, const std::string& input, F&& f)
{
( (same(input, typename Ts::name{}) && (f(Ts{}), true) ) || ...);
}
Checking for equality between std::string and ct_str is annoying, but doable:
template <std::size_t... Is, char... Cs>
bool same_impl(const std::string& s,
std::integer_sequence<char, Cs...>,
std::index_sequence<Is...>)
{
return ((s[Is] == Cs) && ...);
}
template <char... Cs>
bool same(const std::string& s, std::integer_sequence<char, Cs...> seq)
{
return s.size() >= sizeof...(Cs)
&& same_impl(s, seq, std::make_index_sequence<sizeof...(Cs)>{});
}
final result live on wandbox.org
Note that this answer uses C++17 fold expressions. You can replace them in C++14 with one of the following techniques:
Recursive variadic template function, where the base case returns the default accumulation value, and the recursive case performs an operation between the tail and the head.
C++11 pack expansion tricks such as for_each_argument.
The dispatching does short-circuit:
( (same(input, typename Ts::name{}) && (f(Ts{}), true) ) || ...);
This fold expression will stop at the first invocation of f thanks to the , true expression and the || operator.
empirical proof on wandbox.org

c++ Default paramaters: is it possible to override a default parameter without overriding earlier default parameters

I have a function:
int function(int a, int b = 1, int c = 2){
return a+b+c;
}
I want to set the value of the "c" variable to 3, but don't want to set the value of "b"
In a language like python I can do this:
function(23,c=3)
However in c++ I cant find a way to do something like that. All examples I could find involved setting the value of "b" before the value of "c", like this:
function(23,1,3);
How can I set the value of a default parameter directly?
This is not possible in C++ (at least not directly). You have the provide all parameters up to the last one you want to provide, and in the order given by the declaration.
You can not do that in C++.
As a workaround you could wrap all parameters as fields with default value in a class (or a struct). You can then have multiple constructors for that class that allow you to set only those fields you are really interested in changing with respect to default.
It is possible in c++... if you're willing to jump through some hoops.
For fun, here is an example of how it might be done:
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
//
// utility to check whether a type is in a list of types
//
template<class T, class...Ts> struct is_in;
template<class T, class U>
struct is_in<T, U>
: std::is_same<T, U>::type {};
template<class T, class U, class...Rest>
struct is_in<T, U, Rest...>
: std::integral_constant<bool, std::is_same<T, U>::value || is_in<T, Rest...>::value>
{};
//
// a wrapper around fundamental types so we can 'name' types
//
template<class Type, class Tag>
struct fundamental {
using value_type = Type;
using tag_type = Tag;
fundamental(Type x) : _x(x) {}
operator const Type&() const { return _x; }
operator Type&() { return _x; }
Type _x;
};
//
// a utility to figure out a fundamental type's value or to take it's default value if it's not present
//
template<class Fundamental, class Tuple, typename = void>
struct value_of_impl
{
static typename Fundamental::value_type apply(const Tuple& t)
{
return Fundamental::tag_type::dflt;
}
};
template<class Fundamental, class...Types>
struct value_of_impl<Fundamental, std::tuple<Types...>, std::enable_if_t<is_in<Fundamental, Types...>::value>>
{
static typename Fundamental::value_type apply(const std::tuple<Types...>& t)
{
return typename Fundamental::value_type(std::get<Fundamental>(t));
}
};
template<class Fundamental, class Tuple>
decltype(auto) value_of(const Tuple& t)
{
return value_of_impl<Fundamental, Tuple>::apply(t);
}
//
// some tag names to differentiate parameter 'name' types
//
struct a_tag { static constexpr int dflt = 0; };
struct b_tag { static constexpr int dflt = 1; };
struct c_tag { static constexpr int dflt = 2; };
//
// define some parameter 'names'
//
using a = fundamental<int, a_tag>;
using b = fundamental<int, b_tag>;
using c = fundamental<int, c_tag>;
//
// the canonical implementation of the function
//
void func(int a, int b, int c)
{
std::cout << a << ", " << b << ", " << c << std::endl;
}
//
// a version that forwards the values of fundamental types in a tuple, or their default values if not present
//
template<class...Fundamentals>
void func(std::tuple<Fundamentals...> t)
{
func(value_of<a>(t),
value_of<b>(t),
value_of<c>(t));
}
//
// a version that converts a variadic argument list of fundamentals into a tuple (that we can search)
//
template<class...Fundamentals>
void func(Fundamentals&&...fs)
{
return func(std::make_tuple(fs...));
}
//
// a test
//
using namespace std;
auto main() -> int
{
func();
func(a(5));
func(c(10), a(5));
func(b(20), c(10), a(5));
return 0;
}
expected output:
0, 1, 2
5, 1, 2
5, 1, 10
5, 20, 10
You can't do that directly, but you can use Named Parameter Idiom (although criticized).
The idea is to create an object encapsulating all parameters, initialize it using method chaining and finally call the function, so the code would look like:
int v = function(params(23).c(3));
Something like this could be done with the named parameter idiom. Here's how it might look in use to have optional parameters (sans the default parameter values):
/*
int function(int a, int b = 1, int c = 2){
return a+b+c;
}
*/
int function( Parameters &p ) {
/* ... */
}
void someOtherFunction() {
function( Parameters().parmW(/*...*/)
/* parmX was omitted here */
.parmY(/*...*/)
.parmZ(/*...*/)
);
Adding default parameters could be done in a few ways. function could be replaced with a class whose purpose is to perform those actions. Parameters could also be written to know which flags were set, then function passes in default values before it begins executing. I'm sure there's plenty of ways to do this, perhaps some a lot better than what I've suggested.

C++ Metaprogramming: Store integer by type

I want to store integers for given types which should be used during compilation and during runtime.
Up to now I have the following:
template<typename T>
struct my_int { enum { result = -1 }; };
And I specialize for each type:
template<> struct my_int<a_type> { enum { result = 5 }; };
And I can check during compile time (of course the check here would be against another compile time constant):
static_assert(my_int<a_type>::result == 5, "Bla");
Problem:
This works well, as long as the specialization is in the same namespace. But that is an inconvenience I want to get rid of. So I want to be able to use it in every namespace:
namespace foo {
template<> struct my_int<a_type> { enum { result = 5 }; };
}
namespace bar {
template<> struct my_int<b_type> { enum { result = 7 }; };
}
Any ideas how I could do this?
C++11 and boost is ok for my situation, if really needed.
Update: Seems I gave to little information. The types are mainly enum classes. If you're really interested you can see the real implementation here, http://www.codeduce.com/extra/enum_tools, download the zip and in the header line 33, 34.
For some reason I found the problem description easy to misunderstand, but the linked code makes it clear. In C++11 it's easy:
#define SETUP_ENUM_LENGTH(enum_type, length) \
static constexpr int enum_length(enum_type*) { return length; }
and a
for (int i = 0; i < enum_length((Enum*)0); ++i) {
in the right place. Here's a sample:
#include <iostream>
#include <functional>
#include <boost/preprocessor/variadic/size.hpp>
/**
* Macro to setup an enum completely.
* First parameter is the name, following are the states as plain text.
*/
#define DEF_ENUM(name, ...) \
enum class name : uint8_t { __VA_ARGS__ }; \
SETUP_ENUM_LENGTH(name, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))
/**
* Once an enum class is defined, this macro makes the size publicly available.
* Needed by enum_array. Already included in DEF_ENUM.
*/
#define SETUP_ENUM_LENGTH(enum_type, length) \
static constexpr int enum_length(enum_type*) { return length; }
/**
* Function to iterate over all elements of an enum.
*/
template<typename Enum>
void enum_for_each(const std::function<void(Enum e)> &fct) {
for (int i = 0; i < enum_length((Enum*)0); ++i) {
fct(static_cast<Enum>(i));
}
}
namespace n {
DEF_ENUM(demo,u,v,w,x,y,z,a,b,c);
}
namespace m {
DEF_ENUM(demo,a=3,b=1,c=4,d=1,e=5);
}
using std::cout;
int main()
{
enum_for_each<n::demo>([](n::demo e) { cout<<int(e); });
cout<<'\n';
enum_for_each<m::demo>([](m::demo e) { cout<<int(e); });
cout<<'\n';
int ndemo[enum_length((n::demo*)0)];
int mdemo[enum_length((m::demo*)0)];
cout << sizeof ndemo << ' ' << sizeof mdemo << '\n';
}
As a side note, that static_cast<Enum>(i) looks troublesome, does it really do the right thing with the m::demo enum?
To preserve the original templated-enum_length usage and so make the array-allocation usage a bit prettier is easy from here, rename the function enum_length_helper and then
template<typename Enum>
struct enum_length {
enum result=enum_length_helper((Enum*)0);
};
If it is possible for your use-case, you could do specialization on a namespace basis and then aggregate as follows, using C++11 since you mentioned it but can work without.
Assume you have a number of namespaces ns_1 to ns_k like this:
namespace ns_i {
template<class T> struct my_int: std::integral_constant<int, -1> {};
/*...*/
enum e_1 { /*...*/ };
template<> struct my_int<e_1>: std::integral_constant<int, 101> {};
/*...*/
enum e_n { /*...*/ };
template<> struct my_int<e_n>: std::integral_constant<int, 142> {};
/*...*/
}
I assume you already have the means to do a unique numbering. Then you aggregate the my_int from all namespaces like this:
namespace your_lib {
template<
class T,
template<class> class sources... /* any number of template classes,
each taking one type argument */
>
struct Union:
std::integral_constant<int, -1> {}; // default -1 for (empty template list)
template<
class T,
template<class> class source, // match first template
template<class> class sources... // match all but first template
>
struct Union<T, source, sources...>:
std::conditional<
source::value == -1,
union<T, sources...>, // recursively call union on all but first tempalte
source // or if there's a value in first, use it
> {};
template<class T> struct my_int :
Union<T, ns_1::my_int, /*...,*/ ns_k::my_int> {};
/* here you could use boost preprocessor to iterate over the namespaces
since you mentionned it */
}
Here's a solution using functions and ADL:
#include <type_traits>
enum TypeInfo
{
Unknown = 0,
TypeA,
TypeB
};
template <TypeInfo x>
using TInfo = std::integral_constant<TypeInfo, x>;
template <class T>
TInfo<Unknown> TypeInfoFunc(T);
template <class T>
struct GetTypeInfo : decltype(TypeInfoFunc(std::declval<T>())){};
namespace a{
class A{};
TInfo<TypeA> TypeInfoFunc(A);
};
namespace b {
class B{};
TInfo<TypeB> TypeInfoFunc(B);
}
int main()
{
static_assert(GetTypeInfo<a::A>::value == TypeA, "");
static_assert(GetTypeInfo<b::B>::value == TypeB, "");
return 0;
}
The TypeInfoFunc is found using ADL meaning that it can be defined in the same namespace as the class your specializing it for.
EDIT
Based on the comments, I think I understand a bit better now. The solution doesn't change much, simply make your function:
namespace a
{
struct A{};//Or whatever class you want to hold data about your type
A TypeInfoFunc(TInfo<TypeA>);
}
and change GetTypeInfo to
template <TypeInfo x>
struct GetTypeInfo : decltype(TypeInfoFunc(TypeInfo<X>())) {};
This way you can call GetTypeInfo<TypeA> and access all the information in (in this case) class A.
you can avoid the need to specialize a structure if you move the type information in the type itself:
template <int V>
struct TypeInfo { enum { result = V, }; };
class yourClass : TypeInfo<2> //works better if you have an enum instad of number
{}
//...
static_assert(a_type::result == 2);
If you do this you will never have the problem with namespaces if the type is declared you will always have access to type info.

Translating a std::tuple into a template parameter pack

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>());
}