Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface with template member function

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?

like image 389
Exagon Avatar asked May 15 '16 09:05

Exagon


People also ask

Can a member function be a template?

Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates or member function templates. If these member functions take their own template arguments, they are considered to be member function templates.

How do you call a member function of template class?

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6. 2), the member template name must be prefixed by the keyword template .

Can a class member function template be virtual in C++?

No, template member functions cannot be virtual.

How do you call a function in a template?

Defining a Function Template A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What is a member template in Java?

The term member template refers to both member function templates and nested class templates. Member function templates are template functions that are members of a class or class template. Member functions can be function templates in several contexts.

What is the difference between member and function template?

The term member template refers to both member function templates and nested class templates. Member function templates are template functions that are members of a class or class template. Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates ...

Can a local class have a member template?

Local classes are not allowed to have member templates. Member template functions cannot be virtual functions and cannot override virtual functions from a base class when they are declared with the same name as a base class virtual function. The following example shows a templated user-defined conversion:

What is the difference between non-template and template members?

A non-template member function and a template member function with the same name may be declared. In case of conflict (when some template specialization matches the non-template function signature exactly), the use of that name and type refers to the non-template member unless an explicit template argument list is supplied.


1 Answers

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?

like image 198
Barry Avatar answered Sep 19 '22 12:09

Barry