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.
Related
The following code does not work because the inferred template parameter F is std::tuple, whereas I want it to be Foo - the former takes two template parameters and the latter takes one.
#include <tuple>
template <typename T>
using Foo = std::tuple<int, T>;
template <template <typename> class F>
void foo(F<std::string> bar) {}
void test() {
foo(Foo<std::string>());
}
Is there any way to make type inference work with the using statement rather than turning Foo into it's own class?
#include <tuple>
template <typename T>
class Foo {
std::tuple<int, T> bar;
};
template <template <typename> class F>
void foo(F<std::string> bar) {}
void test() {
foo(Foo<std::string>());
}
More Info
I am using C++17's std::variant along with using to alias types that are generic on a single type and I would prefer to declare these with using statements rather than creating wrapper classes for each one. Something like this:
// Assuming Plus, Minus, etc all exist
template <typename T>
using Operation = std::variant<Plus<T>, Minus<T>, Times<T>>;
Building a Haskell-Style Functor
The point of this exercise is to build a small functor library loosely based on Haskell's functor typeclass. I have defined the "typeclass" like this:
template <template <typename> class F>
class Functor {
public:
template <typename T, typename U>
static F<U> fmap(std::function<U(T)> f, F<T> functor);
};
But I also wanted to add some sugar so that you can create a general mapper that will map a function over any function type without pre-specifying the functor type:
template <typename T, typename U>
struct FMap {
FMap(std::function<U(T)> f) : f_(f) {}
template <template <typename> class F>
F<U> operator()(F<T> functor) {
return Functor<F>::fmap(f_, functor);
}
private:
std::function<U(T)> f_;
};
template <typename T, typename U>
FMap<T, U> fmap(std::function<U(T)> f) {
return FMap<T, U>(f);
}
This works well with a simple value-wrapper functor:
template <typename T>
class Value {
public:
Value(T value) : value_(value) {}
const T& value() const {
return value_;
}
private:
T value_;
};
template <>
template <typename T, typename U>
Value<U> Functor<Value>::fmap(std::function<U(T)> f, Value<T> value) {
return Value<U>(f(value.value()));
}
void test() {
std::function<std::string(int)> fn = [](int x) {
return std::to_string(x);
};
auto result = fmap(fn)(Value(42));
// result.value() == "42"
}
Now I am trying to get it to work with a more complicated type that uses std::tuple or std::variant like in the above example.
template <>
template <typename T, typename U>
Foo<U> Functor<Foo>::fmap(std::function<U(T)> f, Foo<T> value) {
return Foo<U>(std::get<0>(value), f(std::get<1>(value)));
}
void test() {
std::function<std::string(int)> fn = [](int x) {
return std::to_string(x);
};
// This is the desirable syntax but it doesn't build
// fmap(fn)(Foo<int>(42, 7));
// This builds but it's super ugly
fmap(fn).operator()<Foo>(Foo<int>(42, 7));
}
Based on the response by SkepticalEmpiricist below, I am thinking that type aliases may not be the way to go here and instead I will have to introduce small wrapper classes - unless there is an SFINAE approach that would get this working.
This library is mostly a curiosity and a means for me to explore some more advanced template concepts - thanks for the help!
So first attempt before we start digging for some SFINAE based trickery to try circumvent the unavoidable:
Alias templates are never deduced by template argument deduction
We could "deduce" the template arguments for the compiler ourselves like this:
#include <tuple>
template <typename T>
using Foo = std::tuple<int, T>;
template <template <typename ...> class F, typename T, typename ...Ts>
void foo(F<T, std::string, Ts...> bar) {}
void test() {
foo(Foo<std::string>());
}
So now we have it compiling for your foo(Foo<std::string>()); call with Foo being the alias template over std::tuple and, more importantly, foo() is still specialized only for Foo<std::string>.
However, to support usage simultaneously of foo() for both the std::tuple alias template and the wrapper class for example, we still don't have it compiling error-free. As in, if we now comment-out the tuple-flavor Foo and bring back in the wrapper class Foo then calling our rewritten foo() will not compile.
To address the issue, let's give it a try with SFINAE to the rescue and replace the last declaration of foo() with this code:
template <template <typename ...> class F, typename T, typename ...Ts,
typename std::enable_if_t<std::is_same<F<T, Ts...>,
std::tuple<T, Ts...>>::value >* = nullptr>
void foo(F<T, std::string, Ts...> bar) {}
template <template <typename> class F>
void foo(F<std::string> bar) {}
Now you can call foo() for instances of both wrapper class of tuples and alias template for tuples. You could implement in the same fashion for std::variant as well.
With:
template <typename T> using Foo = std::tuple<int, T>;
template <template <typename> class F> void foo(F<std::string> bar) {}
void test() { foo(Foo<std::string>()); }
Foo<std::string> is std::tuple<int, std::string>.
so test is
void test() { foo(std::tuple<int, std::string>()); }
How do you expect compiler deduce from tuple from which alias it come ?
we might have
template <typename T> using Bar = std::tuple<int, std::string>;
template <typename T> using Bar2 = std::tuple<some_trait<T>::type, some_trait<T>::type2>;
// ...
A possible workaround might be:
template <typename T, typename U>
Foo<U> fmap(std::function<U(T)> f, Foo<T> value)
{
return Foo<U>(std::get<0>(value), f(std::get<1>(value)));
}
With calling syntax:
fmap(fn, Foo<int>(42, 7));
I want to implement a class template that:
behaves like a function
it's input and output variables are all shared.
relatively easy to use.
As a result, I construct the following:
// all input/output variable's base class
class basic_logic_parameter;
// input/output variable, has theire value and iterators to functions that reference to this variable
template <typename FuncIterator, typename ValueType>
class logic_parameter
:public basic_logic_parameter
{
private:
std::list<FuncIterator> _refedFuncs;
ValueType _val;
public:
};
// all `function`'s base class
class basic_logic_function
{
public:
virtual ~basic_logic_function() = 0;
};
// the function, has input/output variable
template <typename FuncIterator, typename R, typename... Args>
class logic_function_base
:public basic_logic_function
{
private:
std::shared_ptr<logic_parameter<FuncIterator, R>> _ret;
std::tuple<std::shared_ptr<logic_parameter<FuncIterator, Args>>...> _args;
public:
template <std::size_t N>
decltype(auto) arg()
{
return std::get<N>(_args);
}
template <std::size_t N>
struct arg_type
{
typedef std::tuple_element_t<N> type;
};
template <std::size_t N>
using arg_type_t = arg_type<N>::type;
decltype(auto) ret()
{
return _ret;
}
};
I wish to use as these like:
// drawing need color and a pen
struct Color
{
};
struct Pen
{
};
struct Iter
{
};
class Drawer
:public logic_function_base<Iter, void(Color, Pen)>
{
public:
void draw()
{
arg_type_t<0> pColor; // wrong
}
}
My compiler can not pass this code through, why? I just want convert a template parameter pack to std::tuple of std::shared_ptr of them.
for example:
Given struct A, int, struct C, I want to have:
std::tuple<
std::shared_ptr<logic_parameter<A>>,
std::shared_ptr<logic_parameter<int>>,
std::shared_ptr<logic_parameter<C>>,
>
The problem (once the small errors are fixed1) is that you instantiate:
logic_function_base<Iter, void(Color, Pen)>
...meaning that FuncIterator is Iter and R is void(Color, Pen), so Args is emtpy <>, so decltype(_args) is an empty std::tuple<>, and your code fails to obtain the type of the 0th element of an empty tuple, which is legit.
What you want is partial specialization of logic_function_base:
template <typename F, typename T>
class logic_function_base;
template <typename FuncIterator, typename R, typename... Args>
class logic_function_base<FuncIterator, R(Args...)>: public basic_logic_function {
};
1 Small mistakes in your current code:
template <std::size_t N>
struct arg_type
{
typedef std::tuple_element_t<N, decltype(_args)> type; // Missing the tuple type
};
template <std::size_t N>
using arg_type_t = typename arg_type<N>::type; // Missing a typename
This may not answer your whole question, but you could use the following trait to wrap tuple element types.
template <typename T> struct wrap;
template <typename... T>
struct wrap<std::tuple<T...>> {
using type = std::tuple<std::shared_ptr<logic_parameter<T>>...>;
}
template <typename T>
using wrap_t = typename wrap<T>::type;
You can then use it like this:
std::tuple<int,double,char> t1;
wrap_t<decltype(t)> t2;
The type of t2 is std::tuple<std::shared_ptr<logic_parameter<int>>,std::shared_ptr<logic_parameter<double>>,std::shared_ptr<logic_parameter<char>>>.
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.
I am somewhat new to template programming, so this might be a dumb question. I am trying to use variadic templates to check whether a class has a member (called member) or not. To do this, I have written the class
has_member.
#include <iostream>
using namespace std;
class ClassWithMember
{
public:
int member;
};
class ClassWithoutMember
{
};
template <typename T>
class has_member
{
template <typename... C>
class tester: public std::false_type
{
};
template <typename First>
class tester<First>: public std::true_type
{
void tester_fn(decltype(First::member));
};
public:
enum { value = tester<T>::value };
};
template<typename T1>
void my_function(const std::enable_if_t<has_member<T1>::value, T1> &obj)
{
cout<<"Function for classes with member"<<endl;
}
template<typename T1>
void my_function(const std::enable_if_t<!has_member<T1>::value, T1> &obj)
{
cout<<"Function for classes without member"<<endl;
}
int main()
{
ClassWithMember objWithMember;
ClassWithoutMember objWithoutMember;
my_function<ClassWithMember> (objWithMember);
my_function<ClassWithoutMember> (objWithoutMember);
}
I was expecting that by SFINAE, the substitution of the specialized template with classes without the member would fail silently and fall back to the general template. But I get the error:
trial.cpp: In instantiation of ‘class has_member<ClassWithoutMember>::tester<ClassWithoutMember>’:
trial.cpp:28:10: required from ‘class has_member<ClassWithoutMember>’
trial.cpp:38:41: required by substitution of ‘template<class T1> void my_function(std::enable_if_t<(! has_member<T1>::value), T1>&) [with T1 = ClassWithoutMember]’
trial.cpp:49:54: required from here
trial.cpp:24:14: error: ‘member’ is not a member of ‘ClassWithoutMember’
void tester_fn(decltype(First::member));
SFINAE only applies in the immediate context of the substitution. Substitution failure outside of that is an error. That's the issue you're running into:
has_member<ClassWithoutMember>::value // error
That's because the substitution failure doesn't occur in the declaration of has_member or tester, it occurs in the definition. That is too late. You need to push it much earlier. You can use void_t to push it into the specialization of has_member:
template <typename... T>
struct make_void { using type = void; };
template <typename... T>
using void_t = typename make_void<T...>::type;
template <typename T, typename = void>
struct has_member : std::false_type { };
template <typename T>
struct has_member<T, void_t<decltype(T::member)>> : std::true_type { };
Now, if there is no T::member, the substitution failure will occur in the immediate context of the substitution while trying to pick the correct specialization of has_member. That substitution failure is not an error, that particular specialization would just be discarded and we end up with false_type as desired.
As a side-note, the way you're using your enable_if_t prevents template deduction. You should prefer to write it this way:
template <typename T1,
std::enable_if_t<has_member<T1>::value>* = nullptr>
void my_function(const T1& obj) { ... }
template <typename T1,
std::enable_if_t<!has_member<T1>::value>* = nullptr>
void my_function(const T1& obj) { ... }
That would let you just write:
my_function(objWithMember);
my_function(objWithoutMember);
Consider a template class C with a policy set via template template parameter and two policy definitions:
template<class T> struct PolicyOne { };
template<class T, int U, int V> struct PolicyTwo { };
template<class T, template<class> class POLICY> struct C { POLICY<T> policy; };
void f()
{
C<int, PolicyOne> mc1;
C<int, PolicyTwo<1, 2> > mc2; // doesn't work this way
}
PolicyTwo doesn't work because of wrong number of template arguments.
Is there a way to use PolicyTwo as POLICY template parameter if you specify the types for the additional template parameters?
I'm using C++03, so alias declarations are not available.
I'm aware of this question, but I don't see a solution to my problem there.
Depending on how the policy is used, you may be able to manage with inheritance in place of alias templates:
template<int U, int V> struct PolicyTwoAdaptor {
template<class T> struct type: PolicyTwo<T, U, V> { }; };
C<int, PolicyTwoAdaptor<1, 2>::type> mc2;
I can't see hwo to solve this with your current mechanism, but you can reverse the way it works and it should compile fine (and even may reduce complexity by removing the class template parameter):
template <typename T> struct PolicyBase { typedef T value_type; };
template<class T> struct PolicyOne : public PolicyBase<T> { };
template<class T, int U, int V> struct PolicyTwo : public PolicyBase<T> { };
template<class POLICY> struct C { POLICY policy; typedef typename POLICY::value_type T; };
void f()
{
C<PolicyOne<int> > mc1;
C<PolicyTwo<int, 1, 2> > mc2; // doesn't work this way
}
The basic idea is to move the type tempalte parameter out of the policy user, and give a fully instantiated policy to it instead. Then the policy provides its template type back to the policy user through a typedef (if needed).