This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add C++17 deduction guide for std::basic_string (P0433R2, partial)


This adds the deduction guide for std::basic_string. The standard says
the guide needs to be constrained to only match types that meet (an
unspecified subset of) the requirements of InputIterators and
Allocators. I've added a new __is_allocator trait for that, which
checks for a nested value_type and checks for an allocate member
function that can be called with a size_t. It's worth noting that
std::allocator<void> does *not* meet that requirement, because it has
no allocate member. (In the terminology of the Networking TS
allocator<void> is a PseudoAllocator, meaning it can be rebound to
obtain an Allocator, but isn't necessarily an Allocator itself.)

I also needed to modify __alloc_traits, so it can only be instantiated
for types that might be allocators (or pseudo-allocators). This
prevents substitution errors outside the immediate context when
argument deduction performs overload resolution on basic_string
constructors, and tries to refer to invalid types such as
__alloc_traits<int>::size_type. For a demonstration of this problem,
consider:

template<typename A>
struct allocator_traits {
 using size_type = typename A::size_type;
};

struct allocator { using size_type = unsigned; };

template<typename T, typename A = allocator>
struct container
{
 using size_type = typename allocator_traits<A>::size_type;

 container(const container&, unsigned, unsigned) { }

 container(size_type, T, const A& = A()) { }
};

int main()
{
 container<char> c(1, '2');
 container d(c, 0, 0);
}

x.cc: In instantiation of 'struct allocator_traits<int>':
x.cc:15:3:   required by substitution of 'template<class T, class A> container(container<T, A>::size_type, T, const A&)-> container<T, A> [with T = int; A = int]'
x.cc:22:22:   required from here
x.cc:3:42: error: 'int' is not a class, struct, or union type
  using size_type = typename A::size_type;
                                         ^

Changing __alloc_traits avoids this, because the substitution failures
happen in the immediate context. The change to __alloc_traits
shouldn't affect any mangled symbols, because that type is only used
internally.

	* include/bits/alloc_traits.h (__is_allocator, _RequireAllocator):
	New trait and alias for detecting Allocator-like types.
	* include/bits/basic_string.h (basic_string): Add deduction guide
	from P0433.
	* include/ext/alloc_traits.h (__gnu_cxx::__alloc_traits): Add template
	parameter with default template argument that causes substitution
	failures for types that cannot be allocators.
	* testsuite/21_strings/basic_string/cons/char/deduction.cc: New.
	* testsuite/21_strings/basic_string/cons/wchar_t/deduction.cc: New.

Tested powerpc64le-linux, committed to trunk.

Attachment: patch.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]