3

I was surprised to find that for some T, decltype(std::declval<T>()) is not legal:

#include <utility>

template<typename T>
using Alias = decltype(std::declval<T>());

// as expected
using A1 = Alias<int>;
using A2 = Alias<int(int)>;

// error: no matching function for call to 'declval<...>()'
using A3 = Alias<int(int) const>;
using A4 = Alias<int(int) volatile>;
using A5 = Alias<int(int) &>;
using A6 = Alias<int(int) &&>;
// and all combinations of the above

cppreference doesn't seem to indicate that this error is expected.

Are there any other types for which declval<T> cannot be used? Where does the spec define these?

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Eric
  • 95,302
  • 53
  • 242
  • 374

1 Answers1

5

Per [declval], the signature of declval is:

template <class T>
add_rvalue_reference_t<T> declval() noexcept;

Therefore, the call is ill-formed if add_rvalue_reference_t<T> cannot occur as a return type specifier.

Qualified function types have a special rule:

A function type with a cv-qualifier-seq or a ref-qualifier (including a type named by typedef-name ([dcl.typedef], [temp.param])) shall appear only as:

  • (6.1) the function type for a non-static member function,

  • (6.2) the function type to which a pointer to member refers,

  • (6.3) the top-level function type of a function typedef declaration or alias-declaration,

  • (6.4) the type-id in the default argument of a type-parameter, or

  • (6.5) the type-id of a template-argument for a type-parameter ([temp.arg.type]).

They cannot be a return type specifier.

Looking through Types, I'm pretty sure qualified function types are the only case.

L. F.
  • 19,445
  • 8
  • 48
  • 82