Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constness of template member in const member function

How is const applied to a template member in a const member function? I found the following to be interesting (this is in VS15):

class TcpSocket;

class TcpThread
{
   TcpSocket* Listener() const;
   std::vector< TcpSocket* > sockets_;
};

TcpSocket* TcpThread::Listener() const
{
   auto s = sockets_.front();
   return s;
}

I added the auto to clarify what was going on. It is deduced as TcpSocket*, so the non-const version of front is being selected. However, if I insert

sockets_.erase(sockets_.begin());

as the first line of code, it fails to compile, essentially saying that sockets_ is const.

It makes sense for it to work as it does, but there is evidently more going on here than simply "treat each member as const in a const member function.

like image 322
anarchitect Avatar asked Jan 25 '16 14:01

anarchitect


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 aren't referred to as member templates or member function templates. If these member functions take their own template arguments, they're considered to be member function templates.

Can const function modify a member?

const member functions Declaring a member function with the const keyword specifies that the function is a "read-only" function that doesn't modify the object for which it's called. A constant member function can't modify any non-static data members or call any member functions that aren't constant.

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 non template class have a template member function?

A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.


2 Answers

sockets_ inside Listener is const. Let's have a look at what front returns:

reference front();
const_reference front() const;

So we'll get a const_reference, in this case a TcpSocket * const&.

This is where your expectation is incorrect. Stripping away the reference for sake of clarity, you expect a const TcpSocket*, it gives you a TcpSocket * const. The former is a pointer to a const TcpSocket, the latter is a const pointer to a TcpSocket.

So what front gives you is a pointer which you can't change to a TcpSocket which you can change.

As such, it's perfectly valid to make a non-const copy of this pointer with its pointee available for modification:

auto s = sockets_.front();
//sockets_.front() returns TcpSocket* const
//s copies it to a TcpSocket*
like image 83
TartanLlama Avatar answered Oct 21 '22 21:10

TartanLlama


It's not that the non-const version of front is called, it's just that you're storing pointers, and then you're putting it into auto which always deduces by-value (and not by reference--for which you need auto& =). Because you're copying the const pointer, you then have your own copy, and so const is omitted for it, unless you explicitly define it that way. That's why you're deducing TcpSocket* instead of TcpSocket* const.

If you want to verify this, try doing auto& s = _sockets.front() and see what type you get then.

Note. too, that since you're storing a pointer, that vector::const_reference you'd get back would be point to a const pointer and not a pointer to const.

The container itself, being const in that scope, means that you can't change its sequence of elements, or what they point to. So you can't say _sockets.erase() nor can you say _sockets[0]. However, since the elements themselves are pointers to a non-const TcpSocket, that means that you can do pretty much whatever you want with them. It's the container you can't fiddle with.

like image 25
Yam Marcovic Avatar answered Oct 21 '22 21:10

Yam Marcovic