I'm trying to write LINQ-style methods for my base class Iterator, which List and Sequence will inherit from, but those two containers will have their own implementations of these methods. The "Where" method was pretty straight forward. The "Select" method is very tricky; you can't have virtual template methods.
template <typename T>
class Iterator {
public:
virtual ~Iterator() {};
// This is illegal, but if it weren't, it would be the functionality I want.
template <typename R>
virtual shared_ptr<IIterator<R>> Select(const function<R(T)>& func) = 0;
virtual shared_ptr<IIterator<T>> Where(const function<bool(T)>& func) = 0;
};
"Select" will allow you to transform a Iterator of type "ham sandwich" to a Iterator of type "lettuce" for example.
HamSandwiches->Select<'Lettuce'>([] (shared_ptr<'HamSandwich'> hs) { return hs->Lettuce; });
Ignore the single quotes.
Since we can't have virtual template functions, I would have to, of course, not make the function virtual. In that case, we have a plain old function, which we should never "hide" its implementation by writing implementations in List and Sequence compared to a virtual function; it would be considered a design flaw.
template <typename T>
class Iterator {
public:
virtual ~Iterator() {};
template <typename R>
shared_ptr<Iterator<R>> Select(const function<R(T)>& func);
virtual shared_ptr<Iterator<T>> Where(const function<bool(T)>& func) = 0;
};
template <typename T>
template <typename R>
shared_ptr<Iterator<R>> Iterator<T>::Select(const function<R(T)>& func) {
//Implementation - What would it be?
}
Now we have to have implementation in our base class, which this implementation needs to be somewhat specific for List and Sequence. From what I've seen, you would start to create protected "implementation functions" to do certain actions within the "Select" that could be overriden by List or Sequence.
I'm not looking for an exact answer here, I'm looking for something that would help me get where I may/should want to be. Does anyone spot any common gotchas or things I may be doing wrong to begin with?
Option 1
The ideas I have seen for implementing LINQ in C++ were not relying on virtual methods at all. Instead each result was returned wrapped in a template class, approximately like this:
template <class T>
class RangeWrapper
{
public:
template <class U>
Select(U u) -> decltype(...) {
return RangeWrapper<SelectRange, U>(_myRange, u);
}
private:
T& _myRange;
};
If you chain a few of those, the return type may become quite big, but that's the price to pay to get everything done at compile time.
Option 2
You could implement type erasure to always return an iterator of type Iterator<T>. This should be pretty easy to achieve using a type erased iterator library on the web (there are many, you could have a look at boost.TypeErasure which is accepted but not yet released).
Alternatively you could use any_range in boost, if you're OK to work with ranges (they map to LINQ more naturely than iterators).
Option 3
If you are not doing this as a training exercise, there are several solutions that are already implemented. Use google. Notably, Microsoft itself is working on a C++ Linq to implement the reactive extensions on top of it.
Related
Motivation: I need to build a base class for a C++17 library that will have overloads for a virtual function based on types that the user identifies at compile time. Basically, when a particular overload of the function is called on the base class, I want to make sure the correct version is called in the derived class. My initial instinct was to build a virtual template function, but of course C++ cannot allow this because the compiler will not know what versions of it to put in the virtual function table. Since I will know all of the types at compile time, however, is it possible to make the base class itself a variadic template and use the template arguments to build the set of overloaded version of the virtual function that would be needed?
Fold expressions are right out because they can't be used to declare functions. Recursive templates seem promising, but I worry that having a long chain of inheritance for the base class will create a performance hit. Here's the working code that I have:
template <typename... Ts> class MyClass;
template <typename T, typename... Ts>
struct MyClass<T, Ts...> : public MyClass<Ts...> {
using MyClass<Ts...>::MyFunction;
virtual bool MyFunction(T in) { return true; }
};
template <>
struct MyClass<> {
virtual bool MyFunction(...) { return false; }
};
Should this technique be sufficient? Or does anyone have other ideas on how I might accomplish this goal?
My other ideas include:
Cap the number of template arguments that can be handled and enable-if each overload based on whether the argument list is long enough to include it. Downside: this technique would be an arbitrary limit on the number of types.
Use a variadic macro to build the class. Downside: This technique would be confusing and inelegant.
Create a function to assign a type to an ID number in the base class, pass it to the derived class as a void * with its id, and translate it back at that point to make the appropriate overloaded call. Downside: this technique would be tricky to keep type safe and to minimize the amount of work the end-user needs to do.
Right now I'm leaning toward implementing the first of these alternatives and doing some performance testing to compare it to my working version, but would love if there is something cleaner that I'm missing.
Your implementation is right for C++14.
C++17 allows variadic using, to avoid recursion:
template <typename T>
struct MyClassImpl
{
virtual ~MyClassImpl() = default;
virtual bool MyFunction(T in) = 0; // or { return true; }
};
template <typename... Ts>
struct MyClass : public MyClassImpl<Ts>...
{
using MyClassImpl<Ts>::MyFunction...;
};
Demo
I have 6 types of datastructure<T>.
All of them contains cover 10-20 common functions (purple) e.g. addFirst().
However, some datastructures has its own 0-5 unique functions (pink).
For example, only MyArray<T> has function addManual(T,int).
In rare cases, some different types of datastructure support a few same special function.
(The real-case table is ~ 10x more complex.)
Here is a short snippet :-
class Vector3D{};
template<class T>class MyArray{
public: void addFirst(T t){/* some code */}
/* other add / remove / query function */
public: void addManual(T t,int internalIndex){/* some code */}
};
template<class T>class MyGrid3D{
public: void addFirst(T t){/*some code */}
/* other add / remove / query function */
public: void addSpecial(T t,Vector3D gridAddress){/* some code*/}
};
It works good so far.
Now, I want to make it usage easier by providing interface Adapter<MyX,T,I>.
The user of my library can identify the internal stored type T and the interface I separately.
Whenever a parameter of function (purple/pink) has type I, I will convert it to T and internally manipulate it as if it has type T.
Here is my prototype :-
template<template<class> class MyX,class T,class I>class Adapter{
private: T convert(I i){/* some logic */ return T();}
MyX<T> database;
public: void addFirst(I i){
database.addFirst(convert(i));
}
};
int main() {
Adapter<MyArray,int,std::string> adapter;
adapter.addFirst(std::string("5.0f"));
std::cout<<"compiled OK";
return 0;
}
It works good (coliru demo), but it doesn't cover special function (purple) e.g. addManual() or addSpecial() .
Question
What is a design pattern / C++ magic to make Adapter support those functions?
Here are my three poor solutions :-
Create many adapter class for each type of datastructure, e.g. AdapterMyArray<T,I> and AdapterMyGrid3D<T,I>.
Improve the first solution by inheritance e.g. AdapterMyArray<T,I> and AdapterMyGrid3D<T,I> derived from AdapterBase<T,I>.
Check type of MyX and use std::enable_if to enable instantiate of those special functions.
I feel that all my solutions are somehow too manual and it will cause some maintainability issue.
Edit: Yakk's solution is good, but I still doubt if there are even better solution.
CRTP.
Have Adapter_addFirst Adapter_addManual etc CRTP helpers. They use CRTP to access database<T> and implement their one (or set of) functions.
Adapter queries database or database<T> via traits class helpers to determine which of the CRTP Adapter_*s it should inherit (publicly) from.
template<class D, class I>
class Adapter_addFirst {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
public:
void addFirst(I i){
self()->database.addFirst(self()->convert(i));
}
};
template<std::size_t I>
struct empty_t {};
template<template<class> class MyX,class T,class I>
class Adapter:
public std::conditional_t<true, Adapter_addFirst<Adapter<MyX, T, I>, I>, empty_t<0>>
{
friend struct Adapter_addFirst<Adapter<MyX, T, I>, I>;
private:
T convert(I i){/* some logic */ return T();}
MyX<T> database;
};
where true is replaced with a test of "should I have addFirst".
Repeat for each of the methods.
Dispatch is static, methods only exist if they should, everything is standard compliant.
You can test for "should I addManual" either via tags on your types, type traits, or even SFINAE test of a call to std::declval<MyX<T>&>().addManual( std::declval<T const&>() ). For the SFINAE case, see can_apply or equivalent.
I am interested in implementing a Java-collection-like environment for C++.
I know this isn't a good idea and so on but I don't really want to use it later, but just learn how to do some advanced OOP.
My problem is I want a base class template collection<T> with purely virtual functions. One of these functions should be map() which takes a std::function<R(T)>. Since map() should be virtual I don't know which return type I should use for it. collection<R> isn't possible because member function templates can't be virtual.
How can I add such map() member function for my collection<T> interface?
How can I add such map member function for my collection<T> interface?
The short answer is: you don't. If I have some collection<int> and I want to map std::to_string onto it, I need to produce a collection<std::string>. But a vector_collection<int> needs to produce a vector_collection<std::string> and a list_collection<int> needs to produce a list_collection<std::string> - so that type transformation itself needs to be virtualized. But you can't have virtual member function templates, so there's no way to express this.
In order for this to work, you would have to have a common base type for all of the objects you're putting in your container and then just have a common facade that you could cast between. That is, you really only have collection<unique_ptr<Object>> where map just gives you a different collection<unique_ptr<Object>>, and you just map your collection_facade<int, collection<unique_ptr<Object>>> into a collection_facade<std::string, collection<unique_ptr<Object>>>. With a lot of work and complete disregard for performance and type safety, you could get there.
This is the advantage of templates. If I want to write map for something like vector, I can just write that:
template <class T, class A, class F, class R = std::result_of_t<F(T)>>
std::vector<R, A> map(std::vector<T, A> const& v, F f) {
std::vector<R, A> mapped;
mapped.reserve(v.size());
for (T const& elem : v) {
mapped.push_back(f(elem));
}
return mapped;
}
or:
template <class T, class A, class F, class R = std::result_of_t<F(T)>>
std::vector<R, A> map(std::vector<T, A> const& v, F f) {
return std::vector<R, A>(
boost::make_transform_iterator(v.begin(), f),
boost::make_transform_iterator(v.end(), f)
);
}
I have to implement map() for each container separately - but I would have to do that anyway. And now I'm not giving anything up. Besides, how often are you writing algorithms that are runtime-container-agnostic?
Implement map as an external template function.
For instance, you can decompose map in two stages, internal virtual producer and external templated consumer.
template<typename T> struct Collection {
// virtual T next(); // Java way
// C++ way
// In simplest cases you can rely on iterator pairs.
struct const_iterator {
T const &operator*() const;
const_iterator &operator++();
}
virtual const_iterator begin() const;
virtual const_iterator end() const;
};
template<typename R, typename T> Collection<R> map(
Collection<T> const &coll, std::function<R(T)> const &f);
To implement essentially complicated containers and monadic compositions you can even deny begin() and end() and write an explicit (partial) template specialization.
in my work we do a lot of pair programming, and i wrote a function that ONLY accepts containers of a SINGLE type or its derivates, but my co-worker is afraid it will fail code review because it looks so damn ugly and says there's gotta be a better way:
here is the signature, the Fruit class is a base class that i renamed Fruit just for this thread:
template <class Container>
typename enable_if<is_base_of<Fruit, typename remove_pointer<typename Container::value_type>::type>::value, void>::type
processFruits(container& fruits)
{
//process the elements and change them if needed. thats why no const
}
what it does is: returns void and enables the function IF its a container AND the type inside the container is a Fruit and/or derivided of fruit. i also used std::remove_pointer because i needed to know the "type" of the pointer (the container will most likely have pointers).
this compiles and works as intended, but as i said i don't know it its the best way to do it, it seems too verbose and might get cut of on code review.
EDIT: this also accepts templated classes, don't have to be containers. is there a way i can limit it to only accept STL containers?
any alternate ideas or is it fine like it is?
thanks in advance.
It is a bit horrible to read.
Well for starters you don't need to say enable_if<B, void> you can just say enable_if<B> and use the default template argument.
You can easily split it into separate pieces:
template <class T>
struct is_fruity
: is_base_of<Fruit, T>
{ };
template <class Container, typename Value = typename Container::value_type>
struct is_fruit_container
: is_fruity<typename remove_pointer<Value>::type>>
{ };
template<class Container>
typename enable_if<is_fruit_container<Container>::value>::type
processFruits(Container& fruits)
{
//process the elements and change them if needed. thats why no const
}
If you have a compiler supporting alias templates you can make it even easier to read:
template<typename Cond>
using Require = typename enable_if<Cond::value>::type;
template<class Container>
Require<is_fruit_container<Container>>
processFruits(Container& fruits)
{
//process the elements and change them if needed. thats why no const
}
this also accepts templated classes, don't have to be containers. is there a way i can limit it to only accept STL containers?
I'm not sure what you mean by "templated classes", it only accepts types with a nested value_type type which is a type derived from Fruit or a pointer to such type, it doesn't have to be a template. To limit it to "STL containers" you need to write a trait to indentify an "STL container", however you want to define that. To do it properly you'd need a trait that tests for begin(), end(), size() members, as well as all the nested types specified by the container requirements, iterator, value_type, etc.
template<typename C, typename Chead, typename... Ctail>
struct static_and
{
static const bool value = C::value && static_and<Chead, Ctail...>::value;
};
template<typename C>
struct static_and<C>
{
static const bool value = C::value;
};
template<typename C>
struct is_container
: static_and<has_begin<C>, has_end<C>, has_iterator<C>, has_value_type<C> /* etc */>
{ };
I know how to specialise a template function, however what I want to do here is specialise a function for all types which have a given method, eg:
template<typename T> void foo(){...}
template<typename T, if_exists(T::bar)>void foo(){...}//always use this one if the method T::bar exists
T::bar in my classes is static and has different return types.
I tried doing this by having an empty base class ("class HasBar{};") for my classes to derive from and using boost::enable_if with boost::is_base_of on my "specialised" version. However the problem then is that for classes that do have bar, the compiler cant resolve which one to use :(.
template<typename T>
typename boost::enable_if<boost::is_base_of(HasBar, T>, void>::type f()
{...}
I know that I could use boost::disable_if on the "normal" version, however I do not control the normal version (its provided by a third party library and its expected for specialisations to be made, I just don't really want to make explicit specialisations for my 20 or so classes), nor do I have that much control over the code using these functions, just the classes implementing T::bar and the function that uses it.
Is there some way to tell the compiler to "always use this version if possible no matter what" without altering the other versions?
EDIT: I tried a different approach using a template class and explicit specialisations, but this is apparently also not allowed...Anyway to make this approach work?
template<typename T>class ImpFoo
{
public:
//error C3637: 'foo' : a friend function definition cannot be a specialization of a function template
template<> friend void foo<T>(){...}
};
...
class SomeClass : public ImpFoo<T>
{
...
SomeType bar(){...}
};
Sadly you are out of luck in this situation as descriped, the best thing you can do is to explicitly specialize the templates as #aaa says.
As you can limit these specializations to a simple forwarding to one central function, the overhead for 20 classes should be bearable. E.g.:
template<class T> my_foo() { /* do the actual work */ }
template<> void foo<MyClass01>() { my_foo<MyClass01>(); }
// ...
template<> void foo<MyClass20>() { my_foo<MyClass20>(); }