C ++ 17 template subtraction guide not used for empty parameter set?

Consider the following example, which can also be viewed at https://godbolt.org/g/Et56cm :

#include <utility>

template <class T> struct success
{
  T value;
  constexpr success(T &&v)
      : value(std::move(v))
  {
  }
  constexpr success(const T &v)
      : value(v)
  {
  }
};
template <> struct success<void>
{
};
template <class T> success(T /*unused*/)->success<T>;
success()->success<void>;

int main(void)
{
    auto a = success{5};        // works
    auto b = success{};         // works
    auto c = success{"hello"};  // works
    auto d = success(5);        // works
    auto e = success();         // FAILS!
    auto f = success("hello");  // works
    static_assert(std::is_same<decltype(a), success<int>>::value, "");
    static_assert(std::is_same<decltype(b), success<void>>::value, "");
    static_assert(std::is_same<decltype(c), success<const char *>>::value, "");
    static_assert(std::is_same<decltype(d), success<int>>::value, "");
    static_assert(std::is_same<decltype(e), success<void>>::value, "");
    static_assert(std::is_same<decltype(f), success<const char *>>::value, "");
    return 0;
}

      

It's amazing what success()

doesn't compile, but success{}

does. I have provided a guide for template output success() -> success<void>

, so I would have thought that success()

would work.

Is this the expected behavior in the C ++ 17 standard or am I missing something?

+3


source to share


1 answer


This is a gcc bug (just reported 81486 ). On output, success()

we synthesize an overload set that consists of:

// from the constructors
template <class T> success<T> foo(T&& ); // looks like a forwarding reference
                                         // but is really just an rvalue reference
template <class T> success<T> foo(T const& );

// from the deduction guides
template <class T> success<T> foo(T ); // this one is a bit redundant
success<void> foo();

      



And define the return type as if it was called as foo()

, which should certainly give you a type success<void>

. It's not a mistake.

+6


source







All Articles