From the below program I learned, that if I declare a function with a cv-qualified return type,
static_assert
's), butstatic_assert
's).Why is the language inconsistent in this regard?
#include <type_traits>
template <auto>
struct ReturnTypeT;
template <class Ret, class... Pars, Ret (*FPtr)(Pars...)>
struct ReturnTypeT<FPtr> : std::type_identity<Ret> {};
template <auto FPtr>
using ReturnType = ReturnTypeT<FPtr>::type;
enum MyEnum {};
class MyClass {};
template <class T>
T returnT();
#define ASSERT_SAME(T1, T2) static_assert(std::is_same_v<T1, T2>)
ASSERT_SAME(ReturnType< returnT<const int> >, const int);
ASSERT_SAME(ReturnType< returnT<const MyEnum> >, const MyEnum);
ASSERT_SAME(ReturnType< returnT<const MyClass> >, const MyClass);
ASSERT_SAME(ReturnType< returnT<volatile int> >, volatile int);
ASSERT_SAME(ReturnType< returnT<volatile MyEnum> >, volatile MyEnum);
ASSERT_SAME(ReturnType< returnT<volatile MyClass> >, volatile MyClass);
ASSERT_SAME(decltype( returnT<const int>() ), /*?*/ int);
ASSERT_SAME(decltype( returnT<const MyEnum>() ), /*?*/ MyEnum);
ASSERT_SAME(decltype( returnT<const MyClass>() ), const MyClass);
ASSERT_SAME(decltype( returnT<volatile int>() ), /*????*/ int);
ASSERT_SAME(decltype( returnT<volatile MyEnum>() ), /*????*/ MyEnum);
ASSERT_SAME(decltype( returnT<volatile MyClass>() ), volatile MyClass);
Online demo. Note, that returning with volatile
types is deprecated since C++20, see here.
This is specified in [expr.type]#2
.
If a prvalue initially has the type "cv
T
", whereT
is a cv-unqualified non-class, non-array type, the type of the expression is adjusted toT
prior to any further analysis.
Source: C++23, C++ latest draft.