What is std declval in C++?
The std::declval is frequently used in templates when the member function that has to be returned is the same, even though the allowed template parameters may not have a constructor. Changes any sort T into a reference sort, allowing portion capacities to be utilized in decltype expressions without having to be articulate constructors.
In some cases, we require the objects we require to supply to an expression in orchestrate to survey it in capacities like Decltype. Those objects may not, in fact, be able to be made, for case, on the off chance that their classes as private or secured constructors donated it.
The std::declval function is useful in C++. It is a declared function template that accepts a parameter called "anything" and returns a rvalue reference. It eliminates the need for us to intentionally declare a function with a bad name in order to have something for our decltype argument: f(std::declval()) decltype
![What is std::declval in C++?](https://static.tutorialandexample.com/cpp/what-is-std-declval-in-cpp1.png)
When we are in a templated context, and the value we wish to retrieve is dependent on a template parameter, it is quite useful. Take into consideration this small type alias for anything that adds two types:
template<typename T, typename U>
using sum_t = decltype(std::declval<T>() + std::declval<U>());
Interpret this as "sum_t is the type that results from adding T to U". Also, please take note that since the expression inside of decltype is never truly evaluated, neither T nor U need to be properly declared when we instantiate the template.
Return Value:
It never returns a value because it cannot be called. Unless T is (maybe CV-qualified) void, in which case the return type is T, the return type is T&&.
However, precisely what type is returned by decltype? We'll slightly simplify the text for a more detailed explanation.
The type of whatever this refers to is the result of decltype if the argument we supply is the name of a variable (e.g., decltype(x) above), function, or member of an object (decltype x.i). The decltype above (y) example demonstrates that reference, const, and volatile specifiers are included in this.
This last guideline is waived when using the structured binding feature of C++17: The type of the bound-to element is the outcome if the name we give to decltype is one of the variables defined in structured binding.
Example:
std::pair<int volatile &&, double&> f(int);
auto const& [a, b] = f(22);
Decltype(a) will return int unsteady&& undoubtedly show disdain toward the truth that the sort of an is int const unsteady& since that's the sort of the primary component of the return regard of f. Decltype(b) will resign twofold& instep of double const& in a comparative way.
Within the occasion that the expression given to decltype isn't reasonable, a title or portion gets to the expression, and the resultant sort depends on the esteemed category of the expression. Decltype(e) is E on the off chance that e could be a regard, E& on the off chance that e is an lvalue, and E&& in the event that e may be an esteem, given that the expression e has sort E.
As the built-in address-of operator returns a value, the above decltype(&X::bar) is merely a member function pointer and not a reference to one.
With the uncommon case of the as-of-now depicted impacts of fundamental official and the reality that a title expression encased in a walled-in area appears that it may be a regard, these rules, in show disdain toward their clear complexity, essentially fulfill what one would expect. It means that instead of decltype(x) yielding x, decltype((x)) will give X& when x is a variable of type X.
Use cases:
Decltype in C++11 is commonly utilized to decide the return sort of a work format that makes an expression based on its format parameters. A clear development may be a common suspect:
When two values of conceivably different sorts are included, any result can be gotten, particularly on the off chance that the chairperson over-burdening appears. For the event, a char const* gets to be a char const* when an int is included in it. On the other hand, a char const* gets to be a std::string when a std::string is included in it. A fuel tank that incorporates a sugar 3d shape included in it is likely to convey an unsteady engine.
Possible implementation:
template<typename T>
typename std::add_rvalue_reference<T>::type declval() noexcept
{
static_assert(false, "declval not allowed in an evaluated context");
}
Use cases:
- Decltype in C++11 is commonly used to determine the return type of a function template that generates an expression based on its template parameters. An easy addition is a common suspect: When two values of potentially different types are added, any result can be obtained, particularly if operator overloading is present.
- For instance, a char const* becomes a char const* when an int is added to it. On the other hand, a char const* becomes a std::string when a std::string is added to it. A fuel tank that has a sugar cube added to it is likely to produce a volatile engine.
Example:
Let us take an example to illustrate the std::decval in C++.
#include <utility> // std::declval
#include <iostream> // std::cout
struct A { // abstract class
virtual int value() = 0;
};
class B : public A { // class with specific constructor
int val_;
public:
B(int i,int j):val_(i*j){}
int value() {return val_;}
};
int main() {
decltype(std::declval<A>().value()) a; // int a
decltype(std::declval<B>().value()) b; // int b
decltype(B(0,0).value()) c; // same as above (known constructor)
a = b = B(10,2).value();
std::cout << a << '\n';
return 0;
}
Output:
20.