Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use decltype(expression)?

Tags:

c++

decltype

I understand why do we need decltype(auto) and it's difference from auto , but I can't get why and when I should/need to use decltype(expression). In all examples on cppreference I can just use decltype(auto), I checked it. Thanks in advance for your help.

like image 944
DoehJohn Avatar asked Jan 24 '23 21:01

DoehJohn


2 Answers

The simplest example I could come up with is this:

void foo(int i) {
    for (decltype(i) j = 0; j < i; ++j) 
        ...
}

Here, the index j automatically has the same type as the upper bound i.

An alternative example is provided by a lambda expression:

[](auto i) {
    for (decltype(i) j = 0; j < i; ++j) 
        ...    
}
like image 69
Evg Avatar answered Feb 04 '23 12:02

Evg


but I can't get why and when I should/need to use decltype(expression)

In C++11 you can use trailing return types but not auto-deduced return types. E.g.:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) { return t + u; }

C++14 equivalent is:

template<typename T, typename U>
decltype(auto) add(T t, U u) { return t + u; }

Another use is SFINAE, e.g. detecting existence of a member function with a specific name:

#include <iostream>

template<class T>
auto test_has_f(T* p) -> decltype(static_cast<void>(p->f()), std::true_type{}); // Cast to void to avoid user-defined operator,(), if any.

std::false_type test_has_f(void*);

template<class T>
using HasF = decltype(test_has_f(static_cast<T*>(0)));

struct A {};
struct B { void f(); };

int main() {
    std::cout << HasF<A>::value << '\n'; // Outputs 0.
    std::cout << HasF<B>::value << '\n'; // Outputs 1.
}
like image 45
Maxim Egorushkin Avatar answered Feb 04 '23 10:02

Maxim Egorushkin