VS2010 C++ variadic template example - c++

I have a class template and I can't seem to figure out how to perform a Variadic Template style instantiation.
Here is the "code" so far of what I'm looking for:
template<typename _Classname, typename... Args>
class CFunctorStartExT
{
friend class CXXFactory;
protected:
template<typename U>
CFunctorStartExT(typename U& _functor, Args&... args) :
m_Functor(_functor),
m_args(args)
{
}
virtual bool ProcessLoop(CSomeClass* pThread)
{
return m_Functor(pThread, m_args);
}
protected:
_Classname& m_Functor;
Args... m_args;
};
Obviously this won't compile :). The idea is to create a class that can store the values passed in (if any.. it might just have _Classname/U defined) on the constructor so they can be retrieved later to pass to m_Functor in another function.
First: can Variadic Template even be done in VS2010? I am getting compile problems just with the template declaration error C2143: syntax error : missing ',' before '...' from the line template<typename _Classname, typename... Args>
Second, can what I am trying to accomplish be done? Thanks!

Visual C++ 2010 does not support variadic templates.

I believe the following will do what you want. First you need a utility:
// make_tuple_indices
template <size_t...> struct tuple_indices {};
template <size_t _Sp, class _IntTuple, size_t _Ep>
struct make_indices_imp;
template <size_t _Sp, size_t ..._Indices, size_t _Ep>
struct make_indices_imp<_Sp, tuple_indices<_Indices...>, _Ep>
{
typedef typename make_indices_imp<_Sp+1, tuple_indices<_Indices..., _Sp>, _Ep>::type type;
};
template <size_t _Ep, size_t ..._Indices>
struct make_indices_imp<_Ep, tuple_indices<_Indices...>, _Ep>
{
typedef tuple_indices<_Indices...> type;
};
template <size_t _Ep, size_t _Sp = 0>
struct make_tuple_indices
{
static_assert(_Sp <= _Ep, "make_tuple_indices input error");
typedef typename make_indices_imp<_Sp, tuple_indices<>, _Ep>::type type;
};
Then you can use this to help you expand a tuple holding your arguments:
template<typename _Classname, typename... Args>
class CFunctorStartExT
{
friend class CXXFactory;
protected:
template<typename U>
CFunctorStartExT(U& _functor, Args&... args) :
m_Functor(_functor),
m_args(args...)
{
}
virtual bool ProcessLoop(CSomeClass* pThread)
{
return ProcessLoop(pThread,
typename make_tuple_indices<sizeof...(Args)>::type());
}
protected:
_Classname& m_Functor;
std::tuple<Args...> m_args;
private:
template <std::size_t ...Indx>
bool ProcessLoop(CSomeClass* pThread, tuple_indices<Indx...>)
{
return m_Functor(pThread, std::get<Indx>(m_args)...);
}
};
As far as VS2010 variadic template support: I have no idea.

Variadic templates are a patch upon a kludge upon a hack -- you're not going to enjoy this. The way to do this (off the top of my head) is to use template specialization together with inheritance. Something along these lines:
template<typename Classname, typename... Args>
class CFunctorStartExT;
template<typename Classname, typename Arg0, typename... Args>
class CFunctorStartExT : private CFunctorStartExT<Classname, Args...> {
protected:
Arg0 m_arg;
};
template<typename Classname>
class CFunctorStartExT {
protected:
Classname &m_Functor;
};
I've never done this before, and haven't tested it, but this is the general idea. You could have a look at a std::tuple implementation for something that actually works.

Related

Hiding template arguments in std::variant

I have a set of template classes that I want to put inside a std::variant. The following works, but is rather ugly (I have many more classes in the variant, with many template parameters).
template <typename T>
struct Type1
{ };
template <typename B, typename C>
struct Type2
{ };
template <typename A, typename B, typename C>
using Variant = std::variant<Type1<A>, Type2<B,C>>;
Is it possible to "hide" the template arguments in a similar way to this? (doesn't compile)
template <typename A>
using Type1T = Type1<A>
template <typename B, typename C>
using Type2T = Type2<B, C>
using Variant = std::variant<Type1T, Type2T>
error: type/value mismatch at argument 1 in template parameter list
for 'template class std::variant'
Adding typename also doesn't seem to work.
You can't use std::variant to do that. You can use std::any, but you can't visit an any.
The problem is that Type1 and Type2 are not types, they are type templates. There is an infinity of instantiations of Type1, which are all unrelated types as far as a visit is concerned.
I suggest you make non-template Type1Base which you derive Type1<T> from, and have a std::variant<std::unique_ptr<Type1Base>, std::unique_ptr<Type2Base>, ...>
Edit - even template_variant is not possible, there is no way to recover which instantiation of the selected template is the active member. If that were possible, you have the complication that every visitor has to have an overload for every instantiation of every template.
Original attempt:
You could write your own template variant, which would have a mix of members similar to std::any and std::variant
template<template<class...> class ... Templates>
class template_variant
{
std::any value;
public:
// constructors, operator=, etc
// Observers
constexpr std::size_t index() const noexcept; // Which template this contains
const std::type_info& type() const noexcept; // returns the typeid of the contained value
// Modifiers
template <template<typename...> class T, class... Args>
T<Args...>&
emplace(Args&&... args)
{
value.emplace<T<Args...>>(std::forward<Args>(args)...);
}
template <size_t I, class... Args>
template_variant_alternative_t<I, variant, Args...>&
emplace(Args&&... args)
{
value.emplace<template_variant_alternative_t<I, variant, Args...>>(std::forward<Args>(args)...);
}
void swap( template_variant& rhs ) noexcept;
// Non-member functions
friend template <std::size_t I, template<class...> class ... Templates, class... Args>
constexpr template_variant_alternative_t<I, template_variant<Templates...>, Args...>&
std::get(template_variant<Templates...>& v)
{
try
{
return std::any_cast<template_variant_alternative_t<I, template_variant<Templates...>, Args...>&>(v.value);
}
catch (std::bad_any_cast & e)
{
throw bad_template_variant_access(e);
}
}
// and &&, and const&, and const&&
template <template<class...> class T, template<class...> class ... Templates, class... Args>
constexpr T<Args...>&
std::get(template_variant<Templates...>& v)
{
try
{
return std::any_cast<T<Args...>&>(v.value);
}
catch (std::bad_any_cast & e)
{
throw bad_template_variant_access(e);
}
}
// and &&, and const&, and const&&
// etc.
};
template <std::size_t I, typename Variant, class... Args>
struct template_variant_alternative;
template <std::size_t I, template<class...> class ... Templates, class... Args>
struct template_variant_alternative<I, template_variant<Templates...>, Args...>
{
using type = // apply Args... to Ith template in Templates
};
template <std::size_t I, typename Variant, class... Args>
using template_variant_alternative_t = template_variant_alternative<I, Variant, Args...>::type;

Unpack all variadic template arguments except last one as type of variable

I have a template class that accepts a variable number of types as arguments. The constructor accepts a pointer to an instance of the class that uses Args... - 1 as parameter type. Searching over the internet I found out that a std::tuple is often used to handle this type of problems, but I don't understand how I could take the template arguments, create a tuple, remove the last type and then unpack the tuple again and store the result in a variable that can be retrieved later by the parent() function.
template<typename ...Args>
class MyClass
{
public:
MyClass(MyClass<Args...> *parent) : parent_(parent) // Should be Args - 1
{
}
MyClass<Args...>* parent()
{
return parent_;
}
private:
MyClass<Args...> *parent_;
};
I found different answers here on StackOverflow about similar topics that involve tuples. This code has been posted on another question and should get a tuple with all parameters except the last one. The problem is that I don't know how to adapt it to unpack that tuple again.
template<typename, typename>
struct concat_tuple { };
template<typename... Ts, typename... Us>
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>>
{
using type = std::tuple<Ts..., Us...>;
};
template <class T>
struct remove_last;
template <class T>
struct remove_last<std::tuple<T>>
{
using type = std::tuple<>;
};
template <class T, class... Args>
struct remove_last<std::tuple<T, Args...>>
{
using type = typename concat_tuple<std::tuple<T>, typename remove_last<std::tuple<Args...>>::type>::type;
};
#include <type_traits>
#include <tuple>
#include <utility>
#include <cstddef>
template <template <typename...> class C, typename... Args, std::size_t... Is>
auto pop_back(std::index_sequence<Is...>) noexcept
-> C<std::tuple_element_t<Is, std::tuple<Args...>>...>&&;
template <typename... Args>
class MyClass
{
using Parent = std::remove_reference_t<
decltype(pop_back<::MyClass, Args...>(std::make_index_sequence<sizeof...(Args) - 1>{}))
>;
public:
explicit MyClass(Parent* parent) : parent_(parent)
{
}
Parent* parent()
{
return parent_;
}
private:
Parent* parent_;
};
template <>
class MyClass<> {};
int main()
{
MyClass<> a;
MyClass<int> b(&a);
MyClass<int, char> c(&b);
MyClass<int, char, float> d(&c);
}
DEMO
The answer for the previous question, before the edit:
#include <tuple>
#include <utility>
#include <cstddef>
template <typename... Args>
class MyClass
{
public:
auto newInstance()
{
return newInstance(std::make_index_sequence<sizeof...(Args) - 1>{});
}
private:
template <std::size_t... Is>
MyClass<typename std::tuple_element<Is, std::tuple<Args...>>::type...> newInstance(std::index_sequence<Is...>)
{
return {};
}
};
DEMO 2
Why the pop_back function has no body?
This is actually a trait implemented in terms of a function declaration. Alternatively, you could use a more classic solution with a structure specialization:
template <typename T, typename S>
struct pop_back;
template <template <typename...> class C, typename... Args, std::size_t... Is>
struct pop_back<C<Args...>, std::index_sequence<Is...>>
{
using type = C<std::tuple_element_t<Is, std::tuple<Args...>>...>;
};
and then use:
using Parent = typename pop_back<MyClass, std::make_index_sequence<sizeof...(Args) - 1>>::type;
That is, I used a function declaration to shorten the syntax. And it doesn't require a body, since noone is supposed to call this function in an evaluated context.
Why are you using noexcept?
Imagine you have a function:
void foo(MyClass<int, char>) noexcept {}
And elsewhere you want to check whether the call is noexcept:
static_assert(noexcept(foo(pop_back<MyClass, int, char, float>(std::index_sequence<0, 1>{}))), "!");
Without the noexcept specifier, the above assertion would fail, since the call to pop_back would be considered as possibly throwing code.

C++ Variadic class template design

I'm working on a mix-in type Config Reader class which supports reading configuration data from environment, command line, files, etc..
I was kind of following the std::tuple type design:
template <class... Ts> struct ConfigReader {};
template <class T, class... Ts>
class ConfigReader<T, Ts...> : ConfigReader<Ts...>
{
public:
typedef boost::fusion::set<T, Ts...> sequence_type;
ConfigReader(T t, Ts... ts)
: ConfigReader<Ts...>(ts...)
, parameters_(t, ts...)
{
this->init();
}
private:
sequence_type parameters_;
void init()
{
boost::fusion::for_each(parameters_, SetFromEnvironment());
boost::fusion::for_each(parameters_, SetFromCommandLine());
boost::fusion::for_each(parameters_, SetFromConfigFile());
}
};
But I realized that I could also define this without the recursive inheritance
template <class T, class... Ts>
class ConfigReader<T, Ts...>
{
public:
typedef boost::fusion::set<T, Ts...> sequence_type;
ConfigReader(T t, Ts... ts)
: parameters_(t, ts...)
{
this->init();
}
template <class Type>
typename boost::fusion::result_of::value_at_key<Sequence const, Type>::type get()
{
return boost::fusion::at_key<Type>(parameters);
}
private:
sequence_type parameters_;
void init()
{
boost::fusion::for_each(parameters_, SetFromEnvironment());
boost::fusion::for_each(parameters_, SetFromCommandLine());
boost::fusion::for_each(parameters_, SetFromConfigFile());
}
};
The latter case seems to work better because init() is only called once which is really what I want. But now I'm confused as to what are the differences between the two? Am I losing something without the recursive inheritance?
Simplified usage would be.. (Ignoring Parameter type structs)
int main()
{
ConfigReader<Start, End, Resources> configReader(Start(), End("infinity"), Resources());
Start startTime = configReader.get<Start>();
}
The recursive approach makes no sense. Consider an example case where you want:
ConfigReader<A, B, C> reader(A{}, B{}, C{});
In the recursive case, you end up with this hierarchy:
ConfigReader<A, B, C> has three readers: A, B, C
|
|
V
ConfigReader<B, C> has two readers: B, C
|
|
V
ConfigReader<C> has one reader: C
You have 6 readers, when you meant for only 3! What you probably meant when you did the recursive hierarchy is for each instantiation to just have one reader: not all of them. That is:
template <typename T, typename... Ts>
struct ConfigReader : ConfigReader<Ts...> {
T current;
ConfigReader(T t, Ts... ts)
: ConfigReader<Ts...>(ts...)
, current(t)
{ }
};
But what you're doing with the boost fusion set accomplishes that directly. Though, with C++11, you should probably just stick with:
template <typename... T>
struct ConfigReader {
std::tuple<T...> readers;
};
It should suit your purpose.

Select function name based on template parameter

Is there a way to automatically select between multiple non-template functions based on a template parameter?
Example:
class Aggregate
{
public:
std::string asString();
uint32_t asInt();
private:
// some conglomerate data
};
template <typename T>
T get(Aggregate& aggregate)
{
// possible map between types and functions?
return bind(aggregate, typeConvert[T])(); ??
// or
return aggregate.APPROPRIATE_TYPE_CONVERSION();
}
The solution would be nice to throw a compiler error if there is no good conversion available, i.e.
get<double>(aggregate); // compile error
I do not want to use template specialization, i.e
template<>
int get(Aggregate& aggregate)
{
return aggregate.asInt();
}
because it leads to code duplication when your get() function has more then one line of code
The pedestrian way is to define each possible option separately:
template <typename T> T get(Aggregate &); // leave undefined
template <> uint32_t get(Aggregate & a) { return a.asInt(); }
// ...
Absent any more systematic structure that encodes which function serves which conversion, I think this is the best you can do. It may be worth redefining Aggregate, though, to be more introspectible.
You may do something like (require C++11) : (https://ideone.com/UXrQFm)
template <typename T, typename... Ts> struct get_index;
template <typename T, typename... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename Tail, typename... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};
template <typename T, typename Tuple> struct get_index_in_tuple;
template <typename T, typename ... Ts>
struct get_index_in_tuple<T, std::tuple<Ts...>> : get_index<T, Ts...> {};
class Aggregate
{
public:
std::string asString();
uint32_t asInt();
private:
// some conglomerate data
};
template <typename T>
T get(Aggregate& aggregate)
{
using types = std::tuple<uint32_t, std::string>;
auto funcs = std::make_tuple(&Aggregate::asInt, &Aggregate::asString);
return (aggregate.* (std::get<get_index_in_tuple<T, types>::value>(funcs)))();
}

C++11 variadic template template parameters

Keeping the old question. See below for resolution.
It is probably something simple, but still. I have the following C++11 code fragment:
#include <vector>
template <typename... Ts>
struct typelist
{
};
template <typename T>
struct EventContainer
{
typedef T Type;
/// TODO. Ring buffer
std::vector<T> container;
void push(const T& t)
{
EventContainer<T>::container.push_back(t);
}
virtual ~EventContainer()
{
}
};
template <template <typename...> class TL>
class EventStorage:
public EventContainer<Ts>...
{
};
class Event1
{
};
class Event2
{
};
typedef typelist<Event1,Event2> Events12;
int main()
{
EventStorage<Events12> ev;
return 0;
}
How can I make EventStorage inherit EventContainer templeted with each of the types in the typelist. I could do it with Loki:: library, but I want to use C++11 with variadic templates.
Thank you.
Resolution1: Fixing EventStorage template template issue. This will make EventStorage, multiple inherit all EventContainer templated with each type of Ts.
template <typename...>
class EventStorage
{
};
template <typename... Ts>
class EventStorage < typelist<Ts...> >:
public EventContainer<Ts>...
{
};
Now I have compile time error, on the following main():
int main()
{
EventStorage<Events12> ev;
Event1 ev1;
ev.push(ev1);
return 0;
}
In function ‘int main()’:
error: request for member ‘push’ is ambiguous
error: candidates are: void EventContainer<T>::push(const T&) [with T = Event2]
error: void EventContainer<T>::push(const T&) [with T = Event1]
Why the compiler is confused? After all I push with specific type.
GCC 4.6.1 here.
Resolution2:
As #Matthieu M. suggested I can present a forwarding method int EventStorage, but at a cost of one extra functin call:
template <typename T>
void push(const T& t)
{
EventContainer<T>::push(t);
}
According to Alexandrescu, the compiler will optimize this forward call as long as parameters are references.
Now the question is officially closed :)
Is there any reason for introducing the typelist in the first place ?
template <typename T> struct Template { void push(T) {} };
template <typename... Args>
class Storage: public Template<Args>...
{
public:
// forwarding...
template <typename T>
void push(T t) {
Template<T>& me = *this;
me.push(t);
}
};
int main() {
Storage< int, char > storage;
}
This works and you can typedef the whole Storage<...> bit.
EDIT: Following on comments regarding the possibility to "combine" types.
There are two solutions:
template <typename...> struct CombineStorage;
template <typename... A, typename... B>
struct CombineStorage<Storage<A...>, Storage<B...>> {
typedef Storage<A..., B...> type;
};
Or simply provide a typelist adapter:
template <typename... Args>
class Storage<typelist<Args...>>: public Storage<Args...> {};
At the moment, you're never even passing a typelist instantiation to the EventStorage, just the typelist template. So currently, there is no type pack to expand.
However, you should be able to unpack the typelist with a specialization and work with type packs otherwise:
template <typename...> class EventStorage;
template <typename Head, typename... Tail> class EventStorage<Head, Tail...>
: public EventContainer<Head>, EventStorage<Tail...>
{
using EventContainer<Head>::push;
using EventStorage<Tail...>::push;
};
// allows you to pass typelists for convenience
template <typename... TL> class EventStorage<typelist<TL...>>
: public EventStorage<TL...>
{
using EventStorage<TL...>::push;
};
The using declarations just pull all the push methods into the same overload set, which seems to work for me.
The alternative would be to add a template method (maybe just to the toplevel typelist specialization) which explicitly forwards to this->EventContainer<T>::push, but it would require an exact type match.