Patchwork Implement N3642 - User-defined Literals for Standard Library Types

login
register
mail settings
Submitter Ed Smith-Rowland
Date May 31, 2013, 3:06 p.m.
Message ID <51A8BC85.10908@verizon.net>
Download mbox | patch
Permalink /patch/247972/
State New
Headers show

Comments

Ed Smith-Rowland - May 31, 2013, 3:06 p.m.
On 05/31/2013 10:41 AM, Daniel Kr├╝gler wrote:
> 2013/5/31 Ed Smith-Rowland <3dw4rd@verizon.net>:
>> Greetings,
>>
>> This patch implements N3642 - User-defined literals for
>> std::chrono::duration and std::basic_string
>> and N3660 - User-defined literals for std::complex.
>   N3660 was rejected during the Bristol meeting, the main reason being
> the ugliness of the complex-float literal and giving it some time to
> find a possible sore language solution. Is there still the idea to add
> this now?
>
> - Daniel
>
I would offer a modification of the lower-case rule for standard literal 
operators (I know this is bikeshed but I think such things are important 
and obviously prevent ideas from being adopted).

I would say:

   1. Put the precision first in upper case.  As a matter of style I 
prefer 123456L to 123456l for normal literals anyway.  Also, the 
precision snuggles next to the number - then you modify it.  That seems 
logical to me.  Also, if we involve <decimal> in this someday, those 
literals *have* to be all caps (for the old literals).  It seems using 
lower case precision indicators for decimal would be inconsistent.

   2. Use lower case for the other characters except...

   3. If the name derives from a proper name, such as SI unit Farad use 
capitals.  This will make literal operators for units match SI and the 
expectation of users most likely to use such literals.

For complex this gives us:

   std::complex<float>
operator"" Fi(long double imag) noexcept;

   std::complex<float>
operator"" Fi(unsigned long long imag) noexcept;

std::complex<double>
operator"" i(long double imag) noexcept;

std::complex<double>
operator"" i(unsigned long long imag) noexcept;

std::complex<long double>
operator"" Li(long double imag) noexcept;

std::complex<long double>
operator"" Li(unsigned long long imag) noexcept;

This avoids the i_f, and seems more logical to me.

For the issue at hand, I split the patch.

Ed

2013-05-30  Ed Smith-Rowland  <3dw4rd@verizon.net>

	Implement N3660 - User-defined Literals for std::complex,
	part 2 of UDL for Standard Library Types
	* include/std/complex: Add complex literal operators.
	* testsuite/26_numerics/complex/literals/types.cc: New.
	* testsuite/26_numerics/complex/literals/values.cc: New.
	* config/abi/pre/gnu.ver: Add literal operator symbols.
2013-05-30  Ed Smith-Rowland  <3dw4rd@verizon.net>

	Implement N3642 - User-defined Literals for Standard Library Types
	* include/bits/parse_numbers.h: New.
	* include/std/chrono: Add duration literal operators.
	* include/bits/basic_string.h: Add string literal operators.
	* include/Makefile.in: Add parse_numbers.h.
	* include/Makefile.am: Ditto.
	* testsuite/20_util/duration/literals/values.cc: New.
	* testsuite/20_util/duration/literals/types.cc: New.
	* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust.
	* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Adjust.
	* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Adjust.
	* testsuite/21_strings/basic_string/literals/values.cc: New.
	* testsuite/21_strings/basic_string/literals/types.cc: New.
	* config/abi/pre/gnu.ver: Add literal operator symbols.
Index: include/std/complex
===================================================================
--- include/std/complex	(revision 199471)
+++ include/std/complex	(working copy)
@@ -1930,4 +1930,45 @@
 
 #endif  // C++11
 
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace complex_literals {
+
+  inline constexpr std::complex<float>
+  operator"" i_f(long double __num)
+  { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+  inline constexpr std::complex<float>
+  operator"" i_f(unsigned long long __num)
+  { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+  inline constexpr std::complex<double>
+  operator"" i(long double __num)
+  { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+  inline constexpr std::complex<double>
+  operator"" i(unsigned long long __num)
+  { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+  inline constexpr std::complex<long double>
+  operator"" il(long double __num)
+  { return std::complex<long double>{0.0L, __num}; }
+
+  inline constexpr std::complex<long double>
+  operator"" il(unsigned long long __num)
+  { return std::complex<long double>{0.0L, static_cast<long double>(__num)}; }
+
+} // inline namespace complex_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
 #endif  /* _GLIBCXX_COMPLEX */
Index: testsuite/26_numerics/complex/literals/types.cc
===================================================================
--- testsuite/26_numerics/complex/literals/types.cc	(revision 0)
+++ testsuite/26_numerics/complex/literals/types.cc	(working copy)
@@ -0,0 +1,46 @@
+// { dg-options "-std=c++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <type_traits>
+
+void
+test02()
+{
+  using namespace std::literals::complex_literals;
+
+  static_assert(std::is_same<decltype(1.0i_f), std::complex<float>>::value,
+		"1.0i_f is std::complex<float>");
+
+  static_assert(std::is_same<decltype(1i_f), std::complex<float>>::value,
+		"1i_f is std::complex<float>");
+
+  static_assert(std::is_same<decltype(1.0i), std::complex<double>>::value,
+		"1.0i is std::complex<double>");
+
+  static_assert(std::is_same<decltype(1i), std::complex<double>>::value,
+		"1i is std::complex<double>");
+
+  static_assert(std::is_same<decltype(1.0il), std::complex<long double>>::value,
+		"1.0il is std::complex<long double>");
+
+  static_assert(std::is_same<decltype(1il), std::complex<long double>>::value,
+		"1il is std::complex<long double>");
+}
Index: testsuite/26_numerics/complex/literals/values.cc
===================================================================
--- testsuite/26_numerics/complex/literals/values.cc	(revision 0)
+++ testsuite/26_numerics/complex/literals/values.cc	(working copy)
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_hooks.h>
+
+void
+test02()
+{
+  using namespace std::literals::complex_literals;
+
+  std::complex<float> j1 = 1.0i_f;
+  std::complex<float> k1 = 1i_f;
+  std::complex<double> j2 = 2.0i;
+  std::complex<double> k2 = 2i;
+  std::complex<long double> j4 = 4.0il;
+  std::complex<long double> k4 = 4il;
+
+  VERIFY( j1 == std::complex<float>(0.0F, 1.0F) );
+  VERIFY( k1 == std::complex<float>(0.0F, 1.0F) );
+  VERIFY( j2 == std::complex<double>(0.0, 2.0) );
+  VERIFY( k2 == std::complex<double>(0.0, 2.0) );
+  VERIFY( j4 == std::complex<long double>(0.0L, 4.0L) );
+  VERIFY( k4 == std::complex<long double>(0.0L, 4.0L) );
+}
+
+int
+main()
+{
+  test02();
+}
Index: config/abi/pre/gnu.ver
===================================================================
--- config/abi/pre/gnu.ver	(revision 199471)
+++ config/abi/pre/gnu.ver	(working copy)
@@ -1365,6 +1365,14 @@
     # std::get_unexpected()
     _ZSt14get_unexpectedv;
 
+    # std::literals::complex_literals::operator""()
+    _ZNSt8literals16complex_literalsli3i_fEe;
+    _ZNSt8literals16complex_literalsli3i_fEy;
+    _ZNSt8literals16complex_literalsli1iEe;
+    _ZNSt8literals16complex_literalsli1iEy;
+    _ZNSt8literals16complex_literalsli2ilEe;
+    _ZNSt8literals16complex_literalsli2ilEy;
+
 } GLIBCXX_3.4.19;
 
 # Symbols in the support library (libsupc++) have their own tag.

Patch

Index: include/bits/parse_numbers.h
===================================================================
--- include/bits/parse_numbers.h	(revision 0)
+++ include/bits/parse_numbers.h	(working copy)
@@ -0,0 +1,417 @@ 
+// Components for compile-time parsing of numbers -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/parse_numbers.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{chrono}
+ */
+
+#ifndef _PARSE_NUMBERS_H
+#define _PARSE_NUMBERS_H 1
+
+#pragma GCC system_header
+
+// From n3642.pdf except I added binary literals and digit separator '`'.
+
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace __parse_int {
+
+  template<unsigned _Base, char _Dig>
+    struct _Digit;
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '0'>
+    {
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '1'>
+    {
+      static constexpr bool valid{true};
+      static constexpr unsigned value{1};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '2'>
+    {
+      static_assert(_Base > 2, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{2};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '3'>
+    {
+      static_assert(_Base > 3, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{3};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '4'>
+    {
+      static_assert(_Base > 4, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{4};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '5'>
+    {
+      static_assert(_Base > 5, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{5};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '6'>
+    {
+      static_assert(_Base > 6, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{6};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '7'>
+    {
+      static_assert(_Base > 7, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{7};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '8'>
+    {
+      static_assert(_Base > 8, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{8};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '9'>
+    {
+      static_assert(_Base > 9, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{9};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'a'>
+    {
+      static_assert(_Base > 0xa, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xa};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'A'>
+    {
+      static_assert(_Base > 0xa, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xa};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'b'>
+    {
+      static_assert(_Base > 0xb, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xb};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'B'>
+    {
+      static_assert(_Base > 0xb, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xb};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'c'>
+    {
+      static_assert(_Base > 0xc, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xc};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'C'>
+    {
+      static_assert(_Base > 0xc, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xc};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'd'>
+    {
+      static_assert(_Base > 0xd, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xd};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'D'>
+    {
+      static_assert(_Base > 0xd, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xd};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'e'>
+    {
+      static_assert(_Base > 0xe, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xe};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'E'>
+    {
+      static_assert(_Base > 0xe, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xe};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'f'>
+    {
+      static_assert(_Base > 0xf, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xf};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'F'>
+    {
+      static_assert(_Base > 0xf, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xf};
+    };
+
+  //  Digit separator
+  template<unsigned _Base>
+    struct _Digit<_Base, '`'>
+    {
+      static constexpr bool valid{false};
+      static constexpr unsigned value{0};
+    };
+
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, char _Dig, char... _Digs>
+    struct _Digits_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      1U + _Digits_help<_Base, _Digs...>::value :
+	      _Digits_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base, char _Dig>
+    struct _Digits_help<_Base, _Dig>
+    {
+      static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Digits
+    {
+      static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Digits<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, char _Dig, char... _Digs>
+    struct _Power_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      _Base * _Power_help<_Base, _Digs...>::value :
+	      _Power_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base, char _Dig>
+    struct _Power_help<_Base, _Dig>
+    {
+      static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Power
+    {
+      static constexpr unsigned value{_Power_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Power<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs>
+    struct _Number_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      _Pow * _Digit<_Base, _Dig>::value
+	      + _Number_help<_Base, _Pow / _Base, _Digs...>::value :
+	      _Number_help<_Base, _Pow, _Digs...>::value};
+    };
+
+  template<unsigned _Base, unsigned _Pow, char _Dig>
+    struct _Number_help<_Base, _Pow, _Dig>
+    {
+      //static_assert(_Pow == 1U, "power should be one");
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Number
+    {
+      static constexpr unsigned
+	value{_Number_help<_Base, _Power<_Base, _Digs...>::value,
+			   _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Number<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+//  This _Parse_int is the same 'level' as the old _Base_dispatch.
+
+  template<char... _Digs>
+    struct _Parse_int;
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'b', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<2U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'B', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<2U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'x', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<16U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'X', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<16U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<8U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int
+    {
+      static constexpr unsigned long long
+	value{_Number<10U, _Digs...>::value};
+    };
+
+} // namespace __parse_int
+
+
+namespace __select_int {
+
+  template<unsigned long long _Val, typename... _Ints>
+    struct _Select_int_base;
+
+  template<unsigned long long _Val, typename _IntType, typename... _Ints>
+    struct _Select_int_base<_Val, _IntType, _Ints...>
+    : integral_constant
+      <
+	typename conditional
+	<
+	  _Val <= static_cast<unsigned long long>
+		    (std::numeric_limits<_IntType>::max()),
+	  _IntType,
+	  typename _Select_int_base<_Val, _Ints...>::value_type
+	>::type,
+	_Val
+      >
+    { };
+
+  template<unsigned long long _Val>
+    struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val>
+    { };
+
+  template<char... _Digs>
+    struct _Select_int
+    : _Select_int_base<
+	__parse_int::_Parse_int<_Digs...>::value,
+	unsigned char,
+	unsigned short,
+	unsigned int,
+	unsigned long,
+	unsigned long long
+      >
+    { };
+
+} // namespace __select_int
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
+#endif // _PARSE_NUMBERS_H
Index: include/std/chrono
===================================================================
--- include/std/chrono	(revision 199471)
+++ include/std/chrono	(working copy)
@@ -39,6 +39,7 @@ 
 #include <type_traits>
 #include <limits>
 #include <ctime>
+#include <bits/parse_numbers.h> // for literals support.
 
 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
 
@@ -786,4 +787,136 @@ 
 
 #endif // C++11
 
+#if __cplusplus > 201103L
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace chrono_literals {
+
+  namespace __detail {
+
+    using namespace __parse_int;
+
+    template<unsigned long long _Val, typename _Dur>
+      struct _Select_type
+      : conditional<
+	  _Val <= static_cast<unsigned long long>
+		    (numeric_limits<typename _Dur::rep>::max()),
+	  _Dur, void>
+      {
+	static constexpr typename _Select_type::type
+	  value{static_cast<typename _Select_type::type>(_Val)};
+      };
+
+    template<unsigned long long _Val, typename _Dur>
+      constexpr typename _Select_type<_Val, _Dur>::type
+      _Select_type<_Val, _Dur>::value;
+
+  } // __detail
+
+  inline constexpr chrono::duration<long double, ratio<3600,1>>
+  operator"" h(long double __hours)
+  { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::hours>::type
+    operator"" h()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::hours>::value;
+    }
+
+  inline constexpr chrono::duration<long double, ratio<60,1>>
+  operator"" min(long double __mins)
+  { return chrono::duration<long double, ratio<60,1>>{__mins}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::minutes>::type
+    operator"" min()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::minutes>::value;
+    }
+
+  inline constexpr chrono::duration<long double>
+  operator"" s(long double __secs)
+  { return chrono::duration<long double>{__secs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::seconds>::type
+    operator"" s()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::seconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, milli>
+  operator"" ms(long double __msecs)
+  { return chrono::duration<long double, milli>{__msecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::milliseconds>::type
+    operator"" ms()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::milliseconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, micro>
+  operator"" us(long double __usecs)
+  { return chrono::duration<long double, micro>{__usecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::microseconds>::type
+    operator"" us()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::microseconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, nano>
+  operator"" ns(long double __nsecs)
+  { return chrono::duration<long double, nano>{__nsecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::nanoseconds>::type
+    operator"" ns()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::nanoseconds>::value;
+    }
+
+} // inline namespace chrono_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
+
+#endif // __cplusplus > 201103L
+
 #endif //_GLIBCXX_CHRONO
Index: include/bits/basic_string.h
===================================================================
--- include/bits/basic_string.h	(revision 199471)
+++ include/bits/basic_string.h	(working copy)
@@ -3106,6 +3106,43 @@ 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace string_literals {
+
+  inline basic_string<char>
+  operator"" s(const char* __str, size_t __len)
+  { return basic_string<char>{__str, __len}; }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  inline basic_string<wchar_t>
+  operator"" s(const wchar_t* __str, size_t __len)
+  { return basic_string<wchar_t>{__str, __len}; }
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+  inline basic_string<char16_t>
+  operator"" s(const char16_t* __str, size_t __len)
+  { return basic_string<char16_t>{__str, __len}; }
+
+  inline basic_string<char32_t>
+  operator"" s(const char32_t* __str, size_t __len)
+  { return basic_string<char32_t>{__str, __len}; }
+#endif
+
+} // inline namespace string_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
 #endif // C++11
 
 #endif /* _BASIC_STRING_H */
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 199471)
+++ include/Makefile.in	(working copy)
@@ -379,6 +379,7 @@ 
 	${bits_srcdir}/move.h \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
+	${bits_srcdir}/parse_numbers.h \
 	${bits_srcdir}/postypes.h \
 	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 199471)
+++ include/Makefile.am	(working copy)
@@ -117,6 +117,7 @@ 
 	${bits_srcdir}/move.h \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
+	${bits_srcdir}/parse_numbers.h \
 	${bits_srcdir}/postypes.h \
 	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
Index: testsuite/20_util/duration/literals/values.cc
===================================================================
--- testsuite/20_util/duration/literals/values.cc	(revision 0)
+++ testsuite/20_util/duration/literals/values.cc	(working copy)
@@ -0,0 +1,69 @@ 
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+void
+test03()
+{
+  using namespace std::literals::chrono_literals;
+
+  auto jiffy = 23ns;
+  VERIFY( jiffy == std::chrono::nanoseconds(23) );
+  auto fjiffy = 23.0ns;
+  VERIFY( (fjiffy == std::chrono::duration<long double, std::nano>(23.0L)) );
+  auto blip = 14us;
+  VERIFY( blip == std::chrono::microseconds(14) );
+  auto fblip = 14.0us;
+  VERIFY( (fblip == std::chrono::duration<long double, std::micro>(14.0L)) );
+  auto bit = 77ms;
+  VERIFY( bit == std::chrono::milliseconds(77) );
+  auto fbit = 77.0ms;
+  VERIFY( (fbit == std::chrono::duration<long double, std::milli>(77.0L)) );
+  auto warmup = 33s;
+  VERIFY( warmup == std::chrono::seconds(33) );
+  auto fwarmup = 33.0s;
+  VERIFY( (fwarmup == std::chrono::duration<long double, std::ratio<1,1>>(33.0L)) );
+  auto classtime = 50min;
+  VERIFY( classtime == std::chrono::minutes(50) );
+  auto fclasstime = 50.0min;
+  VERIFY( (fclasstime == std::chrono::duration<long double, std::ratio<60,1>>(50.0L)) );
+  auto longtime = 1h + 30min;
+  VERIFY( longtime == std::chrono::minutes(90) );
+  auto flongtime = 1.0h + 30.0min;
+  VERIFY( (flongtime == std::chrono::duration<long double, std::ratio<3600,1>>(1.0L)
+		      + std::chrono::duration<long double, std::ratio<60,1>>(30.0L)) );
+  VERIFY( (flongtime == std::chrono::duration<long double, std::ratio<60,1>>(90.0L)) );
+  auto workday = 8h;
+  VERIFY( workday == std::chrono::hours(8) );
+  auto fworkday = 8.0h;
+  VERIFY( (fworkday == std::chrono::duration<long double, std::ratio<3600,1>>(8.0L)) );
+}
+
+int
+main()
+{
+  test03();
+}
Index: testsuite/20_util/duration/literals/types.cc
===================================================================
--- testsuite/20_util/duration/literals/types.cc	(revision 0)
+++ testsuite/20_util/duration/literals/types.cc	(working copy)
@@ -0,0 +1,74 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <chrono>
+#include <type_traits>
+
+void
+test03()
+{
+  using namespace std::literals::chrono_literals;
+
+  static_assert(std::is_same<decltype(1h), std::chrono::hours>::value,
+		"1h is std::chrono::hours");
+
+  static_assert(std::is_same<decltype(1.0h),
+	std::chrono::duration<long double, std::ratio<3600L, 1L>>>::value,
+	"1.0h is std::chrono::duration<long double, std::ratio<3600L, 1L>>");
+
+  static_assert(std::is_same<decltype(1min), std::chrono::minutes>::value,
+		"1min is std::chrono::minutes");
+
+  static_assert(std::is_same<decltype(1.0min),
+	std::chrono::duration<long double, std::ratio<60L, 1L>>>::value,
+	"1.0min is std::chrono::duration<long double, std::ratio<60L, 1L>>");
+
+  static_assert(std::is_same<decltype(1s), std::chrono::seconds>::value,
+		"1s is std::chrono::seconds");
+
+  static_assert(std::is_same<decltype(1.0s),
+	std::chrono::duration<long double, std::ratio<1L, 1L>>>::value,
+	"1.0s is std::chrono::duration<long double, std::ratio<1L, 1L>>");
+
+  static_assert(std::is_same<decltype(1ms), std::chrono::milliseconds>::value,
+		"1ms is std::chrono::milliseconds");
+
+  static_assert(std::is_same<decltype(1.0ms),
+	std::chrono::duration<long double, std::ratio<1L, 1000L>>>::value,
+	"1.0ms is std::chrono::duration<long double, std::ratio<1L, 1000L>>");
+
+  static_assert(std::is_same<decltype(1us), std::chrono::microseconds>::value,
+		"1us is std::chrono::microseconds");
+
+  static_assert(std::is_same<decltype(1.0us),
+	std::chrono::duration<long double, std::ratio<1L, 1000000L>>>::value,
+	"1.0us is std::chrono::duration<long double, std::ratio<1L, 1000000L>>");
+
+  static_assert(std::is_same<decltype(1ns), std::chrono::nanoseconds>::value,
+		"1ns is std::chrono::nanoseconds");
+
+  static_assert(std::is_same<decltype(1.0ns),
+	std::chrono::duration<long double, std::ratio<1L, 1000000000L>>>::value,
+	"1.0ns is std::chrono::duration<long double, std::ratio<1L, 1000000000L>>");
+}
Index: testsuite/20_util/duration/requirements/typedefs_neg1.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg1.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg1.cc	(working copy)
@@ -31,5 +31,5 @@ 
   test_type d;
 }
 
-// { dg-error "rep cannot be a duration" "" { target *-*-* } 245 }
+// { dg-error "rep cannot be a duration" "" { target *-*-* } 246 }
 // { dg-error "required from here" "" { target *-*-* } 31 }
Index: testsuite/20_util/duration/requirements/typedefs_neg2.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg2.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg2.cc	(working copy)
@@ -32,5 +32,5 @@ 
   test_type d;			// { dg-error "required from here" }
 }
 
-// { dg-error "must be a specialization of ratio" "" { target *-*-* } 246 }
+// { dg-error "must be a specialization of ratio" "" { target *-*-* } 247 }
 // { dg-prune-output "not a member" }
Index: testsuite/20_util/duration/requirements/typedefs_neg3.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg3.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg3.cc	(working copy)
@@ -33,5 +33,5 @@ 
   test_type d;
 }
 
-// { dg-error "period must be positive" "" { target *-*-* } 248 }
+// { dg-error "period must be positive" "" { target *-*-* } 249 }
 // { dg-error "required from here" "" { target *-*-* } 33 }
Index: testsuite/21_strings/basic_string/literals/values.cc
===================================================================
--- testsuite/21_strings/basic_string/literals/values.cc	(revision 0)
+++ testsuite/21_strings/basic_string/literals/values.cc	(working copy)
@@ -0,0 +1,50 @@ 
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  using namespace std::literals::string_literals;
+
+  std::string planet = "Mercury"s;
+  std::wstring wplanet = L"Venus"s;
+  std::string u8planet = u8"Mars"s;
+  std::u16string u16planet = u"Juiter"s;
+  std::u32string u32planet = U"Saturn"s;
+
+  VERIFY( planet == std::string("Mercury") );
+  VERIFY( wplanet == std::wstring(L"Venus") );
+  VERIFY( u8planet == std::string(u8"Mars") );
+  VERIFY( u16planet == std::u16string(u"Juiter") );
+  VERIFY( u32planet == std::u32string(U"Saturn") );
+}
+
+int
+main()
+{
+  test01();
+}
Index: testsuite/21_strings/basic_string/literals/types.cc
===================================================================
--- testsuite/21_strings/basic_string/literals/types.cc	(revision 0)
+++ testsuite/21_strings/basic_string/literals/types.cc	(working copy)
@@ -0,0 +1,47 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <string>
+#include <type_traits>
+
+void
+test01()
+{
+  using namespace std::literals::string_literals;
+
+  static_assert(std::is_same<decltype("Hello"s), std::string>::value,
+		"\"Hello\"s is std::string");
+
+  static_assert(std::is_same<decltype(u8"Hello"s), std::string>::value,
+		"u8\"Hello\"s is std::string");
+
+  static_assert(std::is_same<decltype(L"Hello"s), std::wstring>::value,
+		"L\"Hello\"s is std::wstring");
+
+  static_assert(std::is_same<decltype(u"Hello"s), std::u16string>::value,
+		"u\"Hello\"s is std::u16string");
+
+  static_assert(std::is_same<decltype(U"Hello"s), std::u32string>::value,
+		"U\"Hello\"s is std::u32string");
+}
Index: config/abi/pre/gnu.ver
===================================================================
--- config/abi/pre/gnu.ver	(revision 199471)
+++ config/abi/pre/gnu.ver	(working copy)
@@ -1365,6 +1365,20 @@ 
     # std::get_unexpected()
     _ZSt14get_unexpectedv;
 
+    # std::literals::chrono_literals::operator""()
+    _ZNSt8literals15chrono_literalsli2ns*;
+    _ZNSt8literals15chrono_literalsli2us*;
+    _ZNSt8literals15chrono_literalsli2ms*;
+    _ZNSt8literals15chrono_literalsli1s*;
+    _ZNSt8literals15chrono_literalsli3min*;
+    _ZNSt8literals15chrono_literalsli1h*;
+
+    # std::literals::string_literals::operator""()
+    _ZNSt8literals15string_literalsli1sEPKcm;
+    _ZNSt8literals15string_literalsli1sEPKDim;
+    _ZNSt8literals15string_literalsli1sEPKDsm;
+    _ZNSt8literals15string_literalsli1sEPKwm;
+
 } GLIBCXX_3.4.19;
 
 # Symbols in the support library (libsupc++) have their own tag.