Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between type, value_type and element_type, and when to use each?

Tags:

c++

c++11

I have written a template class that should expose its template parameter, but I am unsure of the appropriate naming.

I have found three different names for essentially the same thing (as far as I can tell):

  • containers, e.g., std::vector use value_type
  • smart pointers, e.g., std::unique_ptr use element_type
  • std::reference_wrapper uses just type

What is the idea behind these different names? What standard algorithms or trait classes depend on which name? Which name should I use for my class (something in between a smart pointer and reference wrapper)?

like image 452
zennehoy Avatar asked Mar 28 '17 07:03

zennehoy


2 Answers

value_type is a member type of containers (and iterators and such). It provides the type of an object, usually a complete object, which you can create or observe. There is no casting between value_type-covariant templates.

element_type is a member type of smart pointers. It provides the type of an observed object. Often smart pointers manage complete objects, but they can also be cast to base subobjects.

type is a member type of metafunctions. Usually it doesn't describe any particular object.

like image 70
Potatoswatter Avatar answered Oct 17 '22 06:10

Potatoswatter


value_type is a part of a big family of things to define when you define containers:

typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef long size_type;
typedef size_type difference_type;

These, in addition to iterators typedefs, are all used by STL algorithms to deal with your container in an agnostic way, without knowing the type of your container. These are the reason why the same algorithm works on std::vector, std::deque and all other STL containers.

On the other hand, std::unique_ptr and std::reference_wrapper have their typedefs for completeness and to make it also possible to the developer to deduce types. For example, consider the situation:

typedef std::vectory<double> MyGreatArray;
//Do stuff with MyGreatArray
//What is the type inside MyGreatArray? I want to assign a single element
MyGreatArray::value_type one_element; //now one_element is a double!
MyGreatArray::iterator MyGreatArrayIt; //now this is an iterator vector<double>
one_element = 1.0;
MyGreatArrayIt = MyGreatArray.begin();

(PS: Of course you can use auto, but this is the case even before C++11)

So you see, you will always have a reference to the type inside the container. It doesn't matter whether it's an STL container or std::unique_ptr, it's just good practice to have a reference of your template type inside your template class, no matter what it's. Since STL and the C++ standard aims toward generality, you'll always find a reference of your template types inside the classes. This will make it easier for everything you do to be independent of the types you put in your templates.

EDIT:

"Why they have different names?" A: Simply to avoid ambiguity. Consider an algorithm that should take a container and requires only a value_type. When the names are different, you add extra protection against catastrophic run-time errors. Remember that everything is becoming type-agnostic. The last thing we want is another source of errors by having everything called value_type.

like image 6
The Quantum Physicist Avatar answered Oct 17 '22 07:10

The Quantum Physicist