I have a function template to echo something from the class, for example:
template<typename T>
void say(const std::vector<T>& ts)
{
for (const auto& t : ts) {
std::cout<<t.getDesc()<<std::endl;
}
}
class Base
{
public
Base();
const std::string& getDesc() const {
return m_desc;
}
protected:
std::string m_desc;
}
All objects inherited from Base can use the template function.
std::vector<Base> v;
Base a;
v.push_back(a)
But when I turn to std::reference_wrapper, the function template does not work. I should write another template to fix it.
template<typename T>
void say(const std::vector<std::reference_wrapper<T>>& ts)
{
for (const auto& t : ts) {
std::cout<<t.get().getDesc()<<std::endl;
}
}
The only difference between them is the std::reference_wrapper::get().
So is there any other way to avoid this annoying code? Or should I write std::reference_wrapper version template for all the function I used?
You don't need to rewrite the whole thing. Just use a level of indirection.
namespace detail {
template<typename T>
constexpr T& get(T &t) { return t; }
template<typename T>
constexpr T const& get(T const &t) { return t; }
template<typename T>
constexpr T& get(std::reference_wrapper<T> rt) { return rt; }
}
template<typename T>
void say(const std::vector<T>& ts)
{
for (const auto& t : ts) {
std::cout<< detail::get(t) <<std::endl;
}
}
The above functions in the detail namespace are reusable of course (though could be better named), and can make all your templates work with std::reference_wrapper.
You can use a helper Unwrap template such as boost::unwrap_reference. Or write your own, copying the code from this other answer:
template< typename T >
struct UnwrapReference;
template< typename T >
struct UnwrapReference { typedef T type; }
template< >
struct UnwrapReference< std::reference_wrapper< T > > { typedef T type; }
Now you can write one version of your function to bind them all (untested):
template<typename T>
void say(const std::vector<T>& ts)
{
for (const UnwrapReference<T>::type &t : ts) {
std::cout<<t.getDesc()<<std::endl;
}
}
Related
I need a 'MultiStack' taking different types of objects, putting each type in a separate stack.
This is what it looks like so far. The open problem is: how to handle the containers for a number of different T
class MultiStack
{
public:
template<typename T>
const T& Get()
{
return Container<T>.back();
}
template<typename T>
void Push( const T& t )
{
Container<T>.push_back( t );
}
template<typename T>
void Pop( const T& /*t*/ )
{
Container<T>.pop_back();
}
private:
// this does not make sense, we obv. need one stack for each T
// template<typename T>
// std::vector<T> Container;
};
Now, I could use the old trick, putting the Container in a member function, like
template<typename T>
auto GetContainer()
{
static std::vector<T> C;
return C;
}
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Is there a better, elegant way? It is conceivable that I know the allowed types beforehand, if that helps realizing it.
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Issue is not multi-threading. initialization would be fine.
You still have to protect/synchronize access though, as regular multi-threading code.
Issue is that the container is not per instance of MultiTask, as it is static.
It is mostly as if MultiTask were a Singleton.
It is conceivable that I know the allowed types beforehand, if that helps realizing it.
That helps, you can then use std::tuple, something like (C++14):
template <typename ... Ts>
class MultiStack
{
public:
template<typename T>
const T& Get() const
{
return GetContainer<T>().back();
}
template<typename T>
void Push(const T& t)
{
GetContainer<T>().push_back(t);
}
template <typename T>
void Pop()
{
GetContainer<T>().pop_back();
}
private:
template <typename T>
const std::vector<T>& GetContainer() const { return std::get<std::vector<T>>(Containers); }
template <typename T>
std::vector<T>& GetContainer() { return std::get<std::vector<T>>(Containers); }
private:
std::tuple<std::vector<Ts>...> Containers;
};
I have a mechanism that uses function overloads to decompose a type into primitives. Here is a sample of the mechanism:
template <typename M, typename T> void process(M&, T&);
template <typename M, typename T>
void process_impl(M& m, const T& t) {
m.write(t);
}
template <typename M, typename T>
void process_impl(M& m, const std::vector<T>& v) {
for (const auto& t: v) {
process(m, t);
}
}
template <typename M, typename T>
void process(M& m, const T& t) {
process_impl(m, t);
}
The use case is to feed a type to process(), which will decompose it into simple types using the overloads of process_impl(). In order to customize the behavior of process() for a specific type, simply overload process():
struct media {
template <typename T> void write(const T& t) { std::cout << t << std::endl; }
};
void process(media& m, const std::string& s) {
process(m, s.size());
}
This code:
media m;
process(m, std::vector<std::string>{"1", "22"});
Outputs:
1
2
Now, I want to wrap media in a class, such that I can further tweak the behavior of process() for my wrapper structure, but I want to preserve the initial behavior of process() regarding media:
template <typename M>
struct debug_media {
template <typename T> void write(const T& t) { m.write(t); }
M m;
};
template <typename M, typename T>
void process(debug_media<M>& d, const T& t) {
std::cout << "debug: ";
process(d.m, t);
}
Ideally, I want the output to be:
debug: 1
debug: 2
But that is not the case, since the overload for debug_media is used only once, for the first invocation; afterward, the overloads of process() that accept a media are used, not the one with debug_media<media>.
I cannot have inheritance between media and debug_media. Is it possible to preserve the behavior of both overloads?
I have put sample code on ideone.
You can add the extra overload:
template <typename M, typename T> void process(debug_media<M>& d, const std::vector<T>& v)
{
for(const auto& t : v) {
process(d, t);
}
}
Live example
How would generic accessors for a property class and their defaults be implemented?
I roughly think it would look as follows:
template<typename Type,
typename Getter = /* How to implement a default setter? */
typename Setter =
class Property {
Getter get; /* Is this right? How is it called then? */
Setter set;
Property(Type value, Getter getter, Setter setter) ...
};
Getter and Setter should be able to be given as lambdas. Is this the right approach, and how do I continue?
You could agree to some kind of structural interface for getters and setters, and then implement something like this:
template <typename T> struct default_getter
{
T & operator()(T & x) const { return x; }
T const & operator()(T const & x) const { return x; }
};
template <typename T> struct default_setter
{
template <typename U>
void operator()(T & x, U && u) const { x = std::forward<U>(u); }
};
template <typename T,
typename Getter = default_getter<T>,
typename Setter = default_setter<T>>
class Property
{
struct PropertyImpl : Getter, Setter
{
T value;
};
PropertyImpl impl;
public:
template <typename U>
void set(U && u)
{
static_cast<Setter &>(impl)(impl.value, std::forward<U>(u));
}
T & get()
{
static_cast<Getter &>(impl)(impl.value);
}
T const & get() const
{
static_cast<Getter const &>(impl)(impl.value);
}
};
Now you can use it like so:
struct Foo
{
Property<Bar> bar;
};
Foo x;
x.bar.get();
x.bar.set(10);
I would propose a solution using std::function.
template<typename T>
struct Property
{
typedef std::function<T()> GetterFunc;
typedef std::function<void(const T&)> SetterFunc;
Property (T value, GetterFunc getter, SetterFunc setter)
: m_getter(getter)
, m_setter(setter)
{
}
Property(T value)
: m_getter( [value](){ return value; }
, m_setter ( [](const T&) { } ) // I have know clue what behaviour you want here
{
}
T Get() { return m_getter(); }
void Set(const T& value) { m_setter(value); }
private:
GetterFunc m_getter;
SetterFunc m_setter;
}
Right now, I have the following to apply two functions to a value and return a 2-value tuple:
template<typename F1, typename F2>
class Apply2
{
public:
using return_type = std::tuple<typename F1::return_type, typename F2::return_type>;
Apply2(const F1& f1, const F2& f2) : f1_(f1), f2_(f2) {}
template<typename T> return_type operator()(const T& t) const
{
return std::make_tuple(f1_(t), f2_(t));
}
protected:
const F1& f1_;
const F2& f2_;
};
I wanted to generalize this to N functions:
template<typename ...F>
class ApplyN
{
public:
using return_type = std::tuple<typename F::return_type...>;
ApplyN(const std::tuple<F...>& fs) : functions_(fs) {}
template<typename T> return_type operator()(const T& t) const
{
return ???;
}
protected:
std::tuple<F...> functions_;
};
I know I probably need to use template recursion somehow, but I can't wrap my head around it. Any ideas?
It took me a while, but here it is (using indices):
template<typename ...F>
class ApplyN
{
public:
using return_type = std::tuple<typename F::return_type...>;
ApplyN(const F&... fs) : functions_{fs...} {}
template<typename T> return_type operator()(const T& t) const
{
return with_indices(t, IndicesFor<std::tuple<F...> >{});
}
protected:
std::tuple<F...> functions_;
template <typename T, std::size_t... Indices>
return_type with_indices(const T& t, indices<Indices...>) const
{
return return_type{std::get<Indices>(functions_)(t)...};
}
};
Someone had an (incomplete) answer before, but s/he erased it - that was my starting point. Anyway, thank you stranger! Thank you R. Martinho Fernandes too!
I want to write my own algorithm (just a function really) that takes a range of iterators. If the iterators are from a map, I want to use the data (iterator->second) value. If the iterator is "normal" like a vector or list, I just want to use the dereferenced iterator value.
I think, value-getter idea is right here, but you can implement it without c++11 and without structs at all, only using functions:
template <typename T>
const T& get(const T& t)
{
return t;
}
template <typename T, typename V>
const V& get(const std::pair<T,V>& t)
{
return t.second;
}
int main()
{
std::vector<int> v = {1};
std::cout << get(*v.begin());
std::cout << "\n----\n";
std::map<int, std::string> m;
m.insert(std::make_pair(0, "sss"));
std::cout << get(*m.cbegin());
}
You can make a value-getter class that extracts the value you're interested in. Note that this approach doesn't work if you store pairs in any container (it transforms all pairs, whether in a map or not). I'd think it would be a much clearer approach to only accept "regular" iterators and let it be callers job to transform map iterators appropriately (as suggested in the comments to your question.)
template<typename T>
struct get {
static auto val(const T& t) -> const T&
{
return t;
}
};
template<typename U, typename V>
struct get<std::pair<U, V>> {
static auto val(const std::pair<U, V>& p) -> const V&
{
return p.second;
}
};
// use like
get<decltype(*iter)>::val(*iter);
Convenience function could look like:
template<class T>
auto getval(const T& t) -> decltype(get<T>::val(t))
{
return get<T>::val(t);
}
You can overload the function based on the input:
void foo(const std::vector<int>::iterator& it1, const std::vector<int>::iterator& it2)
{
//use *it
}
void foo(const std::map<int,int>::iterator& it1, const std::map<int,int>::iterator& it2)
{
//use it->second
}
Edit:
I think this is the closest you can get to what you want to achieve:
template <typename T, typename X>
void foo(T const& x, X const& y)
{
}
template <typename T, typename S>
void foo(const typename std::map<T,S>::iterator& x, const typename std::map<T,S>::iterator& y)
{
}
int main()
{
std::map<int,int> x;
std::vector<int> y;
foo(x.begin(), x.end()); //will call second version
foo(y.begin(), y.end()); //will call first version
}
A trait should do the trick. First the type-deducing helper:
template <typename Iter>
typename iter_value<Iter>::value_type & iter_deref(Iter it)
{
return iter_value<Iter>::deref(it);
}
All we need is something like this:
template <typename Iter>
class iter_value
{
template <typename T> struct aux
{
typedef T type;
static type & deref(Iter it) { return *it; }
};
template <typename U, typename V> struct aux<std::pair<U const, V>>
{
typedef V type;
static type & deref(Iter it) { return it->second; }
};
typedef typename std::iterator_traits<Iter>::value_type type;
public:
typedef typename aux<type>::type value_type;
static value_type & deref(Iter it)
{
return aux<type>::deref(it);
}
};
You can create a function that extracts the value out of the iterator. Then you can overload that based on the type of the iterator. You can use that function in your algorithm. Assuming a vector of ints and a map of string->int, it could look like this:
int getValue(const std::vector<int>::iterator& it)
{
return *it;
}
int getValue(const std::map<std::string, int>::iterator& it)
{
return it->second;
}
Then the algorithm can use the function getValue() to get a value from the iterator.