2

When I was trying to write my own decay_t like this:

#include <utility>
template <class T>
struct auto_decay {
    auto operator () () noexcept {
        return std::declval<T>();
    }
};

template <class T> using decay_t = decltype( (decl_as<decay_impl::auto_decay< T >>())() );

And test it using:

#include <type_traits>
int main() {
    static_assert(is_same<decay_t<int ()&>, int (*)()>{}());
}

I got the following errors:

In file included from test_decay.cc:1:
In file included from ./../src/decay.hpp:4:
In file included from ./../src/utility.hpp:3:
./../src/add_reference.hpp:17:14: error: reference to function type 'int () &' cannot have '&' qualifier
    typedef T&& type;
             ^
./../src/add_reference.hpp:20:1: note: in instantiation of template class 'nxwheels::concept_check::add_rvalue_reference<int () &>' requested here
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
^
./../src/utility.hpp:14:1: note: in instantiation of template type alias 'add_rvalue_reference_t' requested here
auto declval() noexcept -> add_rvalue_reference_t<T>;
^
./../src/decay.hpp:10:16: note: while substituting explicitly-specified template arguments into function template 'declval' 
        return declval<T>();
               ^
./../src/decay.hpp:16:46: note: in instantiation of member function 'nxwheels::concept_check::decay_impl::auto_decay<int () &>::operator()' requested here
template <class T> using decay_t = decltype( (decl_as<decay_impl::auto_decay< T >>())() );
                                             ^
test_decay.cc:17:17: note: in instantiation of template type alias 'decay_t' requested here
    assert_same<decay_t<int (void)&>, int (*)(void)>();
                ^
In file included from test_decay.cc:1:
./../src/decay.hpp:10:16: error: call to function 'declval' that is neither visible in the template definition nor found by argument-dependent lookup
        return declval<T>();
               ^
./../src/decay.hpp:16:46: note: in instantiation of member function 'nxwheels::concept_check::decay_impl::auto_decay<int () &>::operator()' requested here
template <class T> using decay_t = decltype( (decl_as<decay_impl::auto_decay< T >>())() );
                                             ^
test_decay.cc:17:17: note: in instantiation of template type alias 'decay_t' requested here
    assert_same<decay_t<int (void)&>, int (*)(void)>();
                ^
./../src/utility.hpp:14:6: note: 'declval' should be declared prior to the call site
auto declval() noexcept -> add_rvalue_reference_t<T>;
     ^
In file included from test_decay.cc:2:
./../src/concepts/is_same.hpp:18:5: error: static_assert failed
    static_assert(is_same_v<T1, T2>);
    ^             ~~~~~~~~~~~~~~~~~
test_decay.cc:17:5: note: in instantiation of function template specialization 'nxwheels::concept_check::assert_same<int, int (*)()>' requested here
    assert_same<decay_t<int (void)&>, int (*)(void)>();
    ^
3 errors generated.

But when I changed the test into:

#include <type_traits>
int main() {
    static_assert(is_same<decay_t<int (&)()>, int (*)()>{}());
}

Then the test is past, and I can't understand what is the difference between int (&)() and int () &. I checked std::is_funcion and Declaring functions, which both says int () &, not int (&)().

Edit:

And BTW, in the possible implementation section of std::is_funcion, Ret (Args...) & is a specialization for std::is_function. What will they do that?

JiaHao Xu
  • 2,452
  • 16
  • 31

1 Answers1

2

R(&)(Arg...) is a reference to a function, whereas R(Arg...)& is a notation for member function declared

struct test {
  void func() &;
};

EDIT:

#include <type_traits>

struct test {
  void func1() &;
};

template<typename>
struct PM_traits {};

template<class T, class U>
struct PM_traits<U T::*> {
    using member_type = U;
};

int main()
{
    using P = PM_traits<decltype(&test::func1)>::member_type;
    static_assert(std::is_function<P>::value);
}

this complies thanks to the overloads of std::is_function that support R(Arg...)&

Tyker
  • 2,971
  • 9
  • 21
  • What is the difference between what you showed here and a member function declaration without ```&```? And BTW, in the ```possible implementation``` section of [std::is_funcion](https://en.cppreference.com/w/cpp/types/is_function), ```Ret (Args...) &``` is a specialization for std::is_function. What will they do that? – JiaHao Xu Jun 22 '18 at 15:17
  • @JiaHaoXu https://stackoverflow.com/questions/47002799/what-does-the-ampersand-at-the-end-of-member-function-signature-mean – UKMonkey Jun 22 '18 at 15:25
  • @UKMonkey Got it, but why in ```possible implementation``` section of [std::is_funcion](https://en.cppreference.com/w/cpp/types/is_function), ```Ret (Args...) &``` is a specialization for std::is_function? – JiaHao Xu Jun 22 '18 at 15:29
  • @JiaHaoXu because `R(Args...)&` is callable – Tyker Jun 22 '18 at 15:34
  • But ```std::is_function``` doesn't take member function into account; It only takes non-member, thus this makes no sense. – JiaHao Xu Jun 22 '18 at 15:40