C++14: [[deprecated]]

[[deprecated]] is another attribute that is useful to mark something (a function, a method, a variable, a class, etc.) as still valid, but that has been superseded by other newer stuff and that probably will be removed in the future.

In a similar vein to [[nodiscard]], [[deprecated]] can return a message explaining why this entity has been marked as such.

The compiler will show a warning when a deprecated entity is being actually used in our code.

For example, I have this code:

#include <iostream>

void print(const std::string& msg)
{
    std::cout << msg << "\n";
}

int main()
{
    print("Hello world");
}

After that a lot of functions and code started to use my print() function, I realize that a newer version with std::string_view instead of std::string could have better performance and, since I do not want to break any code, I consider having both functions in my system.

So, to discourage the usage of my old function, I mark it as deprecated:

#include <iostream>


void println(std::string_view msg)
{
    std::cout << msg << "\n";
}

[[deprecated("Use println instead")]]
void print(const std::string& msg)
{
    std::cout << msg << "\n";
}

int main()
{
    print("Hello world");
}

But, since I am still using the old version in my main() function, the compiler will return a warning like this one:

main.cpp:17:24: warning: ‘void print(const string&)’ is deprecated: Use println instead [-Wdeprecated-declarations]

That will dissappear when I will replace all the invocation to print() with println().

Advertisement

C++: “auto” return type deduction

Before C++14, when implementing a function template you did not know the return type of your functions, you had to do something like this:

template <typename A, typename B>
auto do_something(const A& a, const B& b) -> decltype(a.do_something(b))
{
  return a.do_something(b);
}

You had to use “decltype” in order to say the compiler: “The return type of this method is the return type of method do_something of object a”. The “auto” keyword used to say the compiler: “The return type of this function is declared at the end”.

Since C++14, you can do something by far simpler:

template <typename A, typename B>
auto do_something(const A& a, const B& b)
{
  return a.do_something(b);
}

In C++14, the compiler deduces the return type of the methods that have “auto” as return type.

Restrictions:

All returned values must be of the same type. My example below does not compile because I am returning an “int” or a “double”.

auto f(int n)
{
	if (n == 1)
		return 1;

	return 2.0;
}

For recursive functions, a return value must be returned before the recursive call in order to let the compiler to know what will be the type of the value to return, as in this example:

auto accumulator(int n)
{
	if (n == 0)
		return 0;

	return n + accumulator(n - 1);
}

C++: Smart pointers, part 3: More on unique_ptr

This is the third post of several posts I wrote related to smart pointers:

  1. Smart pointers
  2. unique_ptr
  3. More on unique_ptr
  4. shared_ptr
  5. weak_ptr

Ok, here I am going to write about two other features that unique_ptr has that I did not mention in my last post.

unique_ptr default behavior consists on take ownership of a pointer created with new and that would normally be released with delete.

Continue reading “C++: Smart pointers, part 3: More on unique_ptr”