Main Content

Expensive use of std::any_cast

An object is cast by-value using std::any_cast when casting by-reference is more efficient

Since R2023b

Description

This defect is raised when both of these conditions are met:

  • You copy the output of std::any_cast where a reference can be used. Consider these situations:

    • You initialize a const reference b by using a copy of the output of std::any_cast:

      const T2& b = std::any_cast<T2>(a);
      It is unnecessary to copy the output of std::any_cast to initialize b because it is possible to initialize b using a reference.

    • You invoke a const member function by using a copy of the output of std::any_cast :

      std::any& a;
      //...
      std::any_cast<std::string>(a).empty();
      Creating a copy of the output is not necessary because it is possible to invoke the const member function empty() by using a reference to a.

  • The output is expensive to copy. Nontrivial objects are typically expensive to copy. See std::is_trivially_copyable in the C++ reference. Trivially copyable objects can also be expensive to copy if it is large.

Risk

Performing a by-value cast (std::any_cast<T>) is more expensive than performing a by-reference cast (std::any_cast<const T&>) if the parameter T is expensive to copy. In situations where copying the parameter is unnecessary, the expensive copy makes your code inefficient. Polyspace® reports a defect on such inefficient code.

Fix

To fix this defect, cast objects by reference instead of by value. That is, replace this usage:

std::any_cast<T>(t)
with this usage:
std::any_cast<const T&>(t)

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

In this example, the const reference b is initialized by using a copy of the output of the operation std::any_cast<std::string>(a). This is inefficient because it is possible to initialize b by using a reference instead of a copy. Polyspace reports a defect.

#include <any>
#include <string>

void foo(std::any& a){
	const std::string& b = std::any_cast<std::string>(a); //Defect
}

Correction — Perform Cast by reference

To fix this defect, perform std::any_cast by reference instead of by value.

#include <any>
#include <string>

void foo(std::any& a){
	const std::string& b = std::any_cast<const std::string&>(a); //No Defect
}

In this example, the const member function empty is invoked by using a copy of the output of the operation std::any_cast< std::string >(a). It is possible to invoke empty by using a const reference instead of a copy, which is more efficient. Polyspace reports a defect.

#include <any>
#include <any>
#include <string>

bool my_empty(const std::any &a){
    return std::any_cast< std::string >(a).empty();
}

	
Correction — Invoke const Member Functions Using const References

To resolve this defect, cast a to an std::string by reference. Thus method uses a const reference to invoke empty instead of a copy, which is more efficient..

#include <any>
#include <string>

bool my_empty(const std::any &a){
    return std::any_cast<const std::string &>(a).empty();
}

	

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_ANY_CAST
Impact: Medium

Version History

Introduced in R2023b