Generic programming with ranges/views not templates? - c++

I'd like to have function that accepts any container of a fixed type. For a example a function that will accept both std::array<float,1> and std::array<float,2>.
I thought this would be possible with ranges but I'm realizing my understanding is quite superficial.
I this possible without templates?
Edit: Can we define a type using the ranges library that will do the equivalent of span but will work for non-contiguous containers? Maybe I didn't phrase my question right, I probably meant view rather than container.

For contiguous ranges, you might use std::span (C++20):
void foo(std::span<float>)
{
// ...
}

Related

Using std::tuple correctly?

I recently learned how to use std::tuple (I had never needed it before then), and was curious as to when it is the proper time to use it over a container? I only ask because std::tuple doesnt feel like a container, since it requires things such as std::get and std::make_tuple.
std::tuples contain a fixed number of elements of varying types. You use it when you want to group together a few objects of different types. I would use it over a struct when the grouping doesn't have any particularly useful semantics. For example, a std::tuple is useful when a function needs to return multiple objects. A container, on the other hand, contains multiple elements of the same type (perhaps a varying amount).
It's more of a replacement for a struct than for a container. However, in most cases you are better off actually defining a struct for readability reasons. Tuples are best used in templates with variable number of arguments.

C++ Is a std::string a container?

This might be a simple question for some of you. But I was wondering if a std::string is a container. By container I mean the containers like for example std::vector, std::list and std::deque.
Since std::basic_string<> accepts other types than integral characters, but also is being optimized by working with character arrays. It isn't really clear to me in which category it falls.
This will compile:
#include <string>
#include <iostream>
int main() {
std::basic_string<int> int_str;
int_str.push_back(14);
return 0;
}
But by adding this line:
std::cout << int_str << std::endl;
It won't. So by these facts I could conclude that an std::basic_string was not intended to work with other types than characters.
It might be a strange question for you. The reason I need to know this is because I'm working on a framework and I'm still not able to determine in which category a "string" would fall.
Yes, the std::basic_string template fulfills all the requirements of the Container concept. However, I think it has stronger requirements on the contained type. Just trying to dig out exactly what.
(This is not Bjarne's Concepts. Just the bit of The Standard labeled "23.2.1 General container requirements".)
According to standards(2003,2011) std::basic_string is a container only for POD types.
I.e. fundamental types or plain structs/classes without constructors, destructors or virtual functions.
But gnu stdlib allow use non-POD types with std::basic_string. Here is an example of working with basic_string and non-POD types.
And if you what to make your example works you should define operator
std::ostream& operator<<(::std::ostream& out, std::basic_string<int> &dat)
{
out << dat[0];
return out;
}
Or something like that.
Well it is safe to say it is not a container at least not in the normal way you would think of an std container.
Most simple example is that you cant put any thing you want in it.
But it does have some classification of a container like the fact that you can put some of the basic types into it even if they are not chars, and perhaps most amazing thing is that you can get an iterator to it as if it was a normal container.
So is it a containr? I would say yes but! it is not an all genery one.

Variadic function declaration VS a function taking a list

While designing a class or a function, which way, that is shown below, is better and why?
class Container {
//Provide this functionality??
void addItemVariadic(const Value& val, ...);
//Or provide this functionality??
void addItemList(const list<Value>& vals);
};
Is it better to provide a function like addItemVariadic(..), or addItemList(..)?
Or is it better to provide a set of such functions, like further taking some iterators, or is it better to limit the functionality, like just taking a list?
Using variadic functions is dangerous
If you ever pass a variable which has not the appriopriate type, it will crash at run time, when calling the function.
On the contrary if you use a std::list, it won't compile simply, and you avoid a crash.
Btw: I advice you to use std::vector instead of std::list in this case.
Edit1 Possible Dupplicate Question. with a nice solution using operator << to inputs all the parameters in one shot.
Edit2 So as to choose between different std::containers, there is a choose-graph as answer to this question. This graph addresses at C++03, it doesn't cover the new containers introduced in C++1.

STL container requierments

Does the standard require that some_container<T>::value_type be T?
I am asking because I am considering different approaches to implementing an STL-compliant 2d dynamic array. One of them is to have 2Darray<T>::value_type be 2Darray_row<T> or something like that, where the array would be iterated as a collection of rows (a little simplified. My actual implementation allows iteration in 3 directions)
The container requirements are a bit funky in the sense that they are actually not used by any generic algorithm. In that sense, it doesn't really matter much.
That said, the requirements are on the interface for containers not on how the container is actually instantiated. Even non-template classes can conform to the various requirements and, in fact, do. The requirement is that value_type is present; what it is defined to depends entirely on the container implementation.
Table 96 in ยง23.2.1 in the standard (c++11) requires a container class X containing objects of type T to return T for X::value_type.
So, if your some_container stores objects of type T, then value_type has to be T.
Either have a nested container (so colArray<rowArray<T> >) or have a single wrapping (2dArray<T>), but don't try to mix them. The nested approach allows you to use STL all the way down (vector<vector<T> >), but can be confusing and doesn't allow you column iterators etc, which you seem to want.
This SO answer addresses using ublas, and another suggests using Boost multi-arrays.
Generally, go for the STL or Boost option if you can. You are unlikely to write something as well by yourself.

Most efficient way to process all items in an unknown container?

I'm doing a computation in C++ and it has to be as fast as possible (it is executed 60 times per second with possibly large data). During the computation, a certain set of items have to be processed. However, in different cases, different implementations of the item storage are optimal, so i need to use an abstract class for that.
My question is, what is the most common and most efficient way to do an action with each of the items in C++? (I don't need to change the structure of the container during that.) I have thought of two possible solutions:
Make iterators for the storage classes. (They're also mine, so i can add it.) This is common in Java, but doesn't seem very 'C' to me:
class Iterator {
public:
bool more() const;
Item * next();
}
Add sort of an abstract handler, which would be overriden in the computation part and would include the code to be called on each item:
class Handler {
public:
virtual void process(Item &item) = 0;
}
(Only a function pointer wouldn't be enough because it has to also bring some other data.)
Something completely different?
The second option seems a bit better to me since the items could in fact be processed in a single loop without interruption, but it makes the code quite messy as i would have to make quite a lot of derived classes. What would you suggest?
Thanks.
Edit: To be more exact, the storage data type isn't exactly just an ADT, it has means of only finding only a specific subset of the elements in it based on some parameters, which i need to then process, so i can't prepare all of them in an array or something.
#include <algorithm>
Have a look at the existing containers provided by the C++ standard, and functions such as for_each.
For a comparison of C++ container iteration to interfaces in "modern" languages, see this answer of mine. The other answers have good examples of what the idiomatic C++ way looks like in practice.
Using templated functors, as the standard containers and algorithms do, will definitely give you a speed advantage over virtual dispatch (although sometimes the compiler can devirtualize calls, don't count on it).
C++ has iterators already. It's not a particularly "Java" thing. (Note that their interface is different, though, and they're much more efficient than their Java equivalents)
As for the second approach, calling a virtual function for every element is going to hurt performance if you're worried about throughput.
If you can (pre-)sort your data so that all objects of the same type are stored consecutively, then you can select the function to call once, and then apply it to all elements of that type. Otherwise, you'll have to go through the indirection/type check of a virtual function or another mechanism to perform the appropriate action for every individual element.
What gave you the impression that iterators are not very C++-like? The standard library is full of them (see this), and includes a wide range of algorithms that can be used to effectively perform tasks on a wide range of standard container types.
If you use the STL containers you can save re-inventing the wheel and get easy access to a wide variety of pre-defined algorithms. This is almost always better than writing your own equivalent container with an ad-hoc iteration solution.
A function template perhaps:
template <typename C>
void process(C & c)
{
typedef typename C::value_type type;
for (type & x : c) { do_something_with(x); }
}
The iteration will use the containers iterators, which is generally as efficient as you can get.
You can specialize the template for specific containers.