[libcxx] r279945 - Implement LWG 2711. Constrain path members.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 28 14:26:02 PDT 2016


Author: ericwf
Date: Sun Aug 28 16:26:01 2016
New Revision: 279945

URL: http://llvm.org/viewvc/llvm-project?rev=279945&view=rev
Log:
Implement LWG 2711. Constrain path members.

Modified:
    libcxx/trunk/include/experimental/filesystem
    libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp
    libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp
    libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp
    libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp
    libcxx/trunk/test/support/test_iterators.h
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/experimental/filesystem
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/filesystem?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/include/experimental/filesystem (original)
+++ libcxx/trunk/include/experimental/filesystem Sun Aug 28 16:26:01 2016
@@ -453,6 +453,9 @@ class _LIBCPP_TYPE_VIS directory_entry;
 template <class _Tp> struct __can_convert_char {
   static const bool value = false;
 };
+template <class _Tp> struct __can_convert_char<const _Tp>
+    : public __can_convert_char<_Tp> {
+};
 template <> struct __can_convert_char<char> {
     static const bool value = true;
     using __char_type = char;

Modified: libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp Sun Aug 28 16:26:01 2016
@@ -246,6 +246,60 @@ void doAppendSourceTest(AppendOperatorTe
   }
 }
 
+
+
+template <class It, class = decltype(fs::path{}.append(std::declval<It>()))>
+constexpr bool has_append(int) { return true; }
+template <class It>
+constexpr bool has_append(long) { return false; }
+
+template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))>
+constexpr bool has_append_op(int) { return true; }
+template <class It>
+constexpr bool has_append_op(long) { return false; }
+
+template <class It>
+constexpr bool has_append() {
+  static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same");
+  return has_append<It>(0) && has_append_op<It>(0);
+}
+
+void test_sfinae()
+{
+  using namespace fs;
+  {
+    using It = const char* const;
+    static_assert(has_append<It>(), "");
+  }
+  {
+    using It = input_iterator<const char*>;
+    static_assert(has_append<It>(), "");
+  }
+  {
+    struct Traits {
+      using iterator_category = std::input_iterator_tag;
+      using value_type = const char;
+      using pointer = const char*;
+      using reference = const char&;
+      using difference_type = std::ptrdiff_t;
+    };
+    using It = input_iterator<const char*, Traits>;
+    static_assert(has_append<It>(), "");
+  }
+  {
+    using It = output_iterator<const char*>;
+    static_assert(!has_append<It>(), "");
+
+  }
+  {
+    static_assert(!has_append<int*>(), "");
+  }
+  {
+    static_assert(!has_append<char>(), "");
+    static_assert(!has_append<const char>(), "");
+  }
+}
+
 int main()
 {
   using namespace fs;
@@ -266,4 +320,5 @@ int main()
     doAppendSourceAllocTest<char>(TC);
     doAppendSourceAllocTest<wchar_t>(TC);
   }
+  test_sfinae();
 }

Modified: libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp Sun Aug 28 16:26:01 2016
@@ -170,6 +170,49 @@ void RunTestCase(MultiStringType const&
   }
 }
 
+template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
+constexpr bool has_assign(int) { return true; }
+template <class It>
+constexpr bool has_assign(long) { return false; }
+template <class It>
+constexpr bool has_assign() { return has_assign<It>(0); }
+
+void test_sfinae() {
+  using namespace fs;
+  {
+    using It = const char* const;
+    static_assert(std::is_assignable<path, It>::value, "");
+    static_assert(has_assign<It>(), "");
+  }
+  {
+    using It = input_iterator<const char*>;
+    static_assert(std::is_assignable<path, It>::value, "");
+    static_assert(has_assign<It>(), "");
+  }
+  {
+    struct Traits {
+      using iterator_category = std::input_iterator_tag;
+      using value_type = const char;
+      using pointer = const char*;
+      using reference = const char&;
+      using difference_type = std::ptrdiff_t;
+    };
+    using It = input_iterator<const char*, Traits>;
+    static_assert(std::is_assignable<path, It>::value, "");
+    static_assert(has_assign<It>(), "");
+  }
+  {
+    using It = output_iterator<const char*>;
+    static_assert(!std::is_assignable<path, It>::value, "");
+    static_assert(!has_assign<It>(), "");
+
+  }
+  {
+    static_assert(!std::is_assignable<path, int*>::value, "");
+    static_assert(!has_assign<int*>(), "");
+  }
+}
+
 int main() {
   for (auto const& MS : PathList) {
     RunTestCase<char>(MS);
@@ -177,4 +220,5 @@ int main() {
     RunTestCase<char16_t>(MS);
     RunTestCase<char32_t>(MS);
   }
+  test_sfinae();
 }

Modified: libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp Sun Aug 28 16:26:01 2016
@@ -265,6 +265,68 @@ void doConcatECharTest(ConcatOperatorTes
   }
 }
 
+
+template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))>
+constexpr bool has_concat(int) { return true; }
+template <class It>
+constexpr bool has_concat(long) { return false; }
+
+template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))>
+constexpr bool has_concat_op(int) { return true; }
+template <class It>
+constexpr bool has_concat_op(long) { return false; }
+template <class It>
+constexpr bool has_concat_op() { return has_concat_op<It>(0); }
+
+template <class It>
+constexpr bool has_concat() {
+  static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same");
+  return has_concat<It>(0) && has_concat_op<It>(0);
+}
+
+void test_sfinae() {
+  using namespace fs;
+  {
+    static_assert(has_concat_op<char>(), "");
+    static_assert(has_concat_op<const char>(), "");
+    static_assert(has_concat_op<char16_t>(), "");
+    static_assert(has_concat_op<const char16_t>(), "");
+  }
+  {
+    using It = const char* const;
+    static_assert(has_concat<It>(), "");
+  }
+  {
+    using It = input_iterator<const char*>;
+    static_assert(has_concat<It>(), "");
+  }
+  {
+    struct Traits {
+      using iterator_category = std::input_iterator_tag;
+      using value_type = const char;
+      using pointer = const char*;
+      using reference = const char&;
+      using difference_type = std::ptrdiff_t;
+    };
+    using It = input_iterator<const char*, Traits>;
+    static_assert(has_concat<It>(), "");
+  }
+  {
+    using It = output_iterator<const char*>;
+    static_assert(!has_concat<It>(), "");
+  }
+  {
+    static_assert(!has_concat<int>(0), "");
+    // operator+=(int) is well formed since it converts to operator+=(value_type)
+    // but concat(int) isn't valid because there is no concat(value_type).
+    // This should probably be addressed by a LWG issue.
+    static_assert(has_concat_op<int>(), "");
+  }
+  {
+    static_assert(!has_concat<int*>(), "");
+  }
+}
+
 int main()
 {
   using namespace fs;
@@ -323,4 +385,5 @@ int main()
     doConcatECharTest<char16_t>(TC);
     doConcatECharTest<char32_t>(TC);
   }
+  test_sfinae();
 }

Modified: libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp Sun Aug 28 16:26:01 2016
@@ -80,6 +80,37 @@ void RunTestCase(MultiStringType const&
   }
 }
 
+void test_sfinae() {
+  using namespace fs;
+  {
+    using It = const char* const;
+    static_assert(std::is_constructible<path, It>::value, "");
+  }
+  {
+    using It = input_iterator<const char*>;
+    static_assert(std::is_constructible<path, It>::value, "");
+  }
+  {
+    struct Traits {
+      using iterator_category = std::input_iterator_tag;
+      using value_type = const char;
+      using pointer = const char*;
+      using reference = const char&;
+      using difference_type = std::ptrdiff_t;
+    };
+    using It = input_iterator<const char*, Traits>;
+    static_assert(std::is_constructible<path, It>::value, "");
+  }
+  {
+    using It = output_iterator<const char*>;
+    static_assert(!std::is_constructible<path, It>::value, "");
+
+  }
+  {
+    static_assert(!std::is_constructible<path, int*>::value, "");
+  }
+}
+
 int main() {
   for (auto const& MS : PathList) {
     RunTestCase<char>(MS);
@@ -87,4 +118,5 @@ int main() {
     RunTestCase<char16_t>(MS);
     RunTestCase<char32_t>(MS);
   }
+  test_sfinae();
 }

Modified: libcxx/trunk/test/support/test_iterators.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_iterators.h?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/test/support/test_iterators.h (original)
+++ libcxx/trunk/test/support/test_iterators.h Sun Aug 28 16:26:01 2016
@@ -53,25 +53,27 @@ public:
     void operator,(T const &) DELETE_FUNCTION;
 };
 
-template <class It>
+template <class It,
+    class ItTraits = It>
 class input_iterator
 {
+    using Traits = std::iterator_traits<ItTraits>;
     It it_;
 
-    template <class U> friend class input_iterator;
+    template <class U, class T> friend class input_iterator;
 public:
     typedef          std::input_iterator_tag                   iterator_category;
-    typedef typename std::iterator_traits<It>::value_type      value_type;
-    typedef typename std::iterator_traits<It>::difference_type difference_type;
+    typedef typename Traits::value_type                        value_type;
+    typedef typename Traits::difference_type                   difference_type;
     typedef It                                                 pointer;
-    typedef typename std::iterator_traits<It>::reference       reference;
+    typedef typename Traits::reference                         reference;
 
     It base() const {return it_;}
 
     input_iterator() : it_() {}
     explicit input_iterator(It it) : it_(it) {}
-    template <class U>
-        input_iterator(const input_iterator<U>& u) :it_(u.it_) {}
+    template <class U, class T>
+        input_iterator(const input_iterator<U, T>& u) :it_(u.it_) {}
 
     reference operator*() const {return *it_;}
     pointer operator->() const {return it_;}
@@ -89,18 +91,18 @@ public:
     void operator,(T const &) DELETE_FUNCTION;
 };
 
-template <class T, class U>
+template <class T, class TV, class U, class UV>
 inline
 bool
-operator==(const input_iterator<T>& x, const input_iterator<U>& y)
+operator==(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
 {
     return x.base() == y.base();
 }
 
-template <class T, class U>
+template <class T, class TV, class U, class UV>
 inline
 bool
-operator!=(const input_iterator<T>& x, const input_iterator<U>& y)
+operator!=(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
 {
     return !(x == y);
 }

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=279945&r1=279944&r2=279945&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Sun Aug 28 16:26:01 2016
@@ -298,7 +298,7 @@
 	<tr><td><a href="http://wg21.link/LWG2707">2707</a></td><td>path construction and assignment should have "string_type&&" overloads</td><td>Oulu</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2709">2709</a></td><td>offsetof is unnecessarily imprecise</td><td>Oulu</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2710">2710</a></td><td>"Effects: Equivalent to ..." doesn't count "Synchronization:" as determined semantics</td><td>Oulu</td><td>Complete</td></tr>
-	<tr><td><a href="http://wg21.link/LWG2711">2711</a></td><td>path is convertible from approximately everything under the sun</td><td>Oulu</td><td></td></tr>
+	<tr><td><a href="http://wg21.link/LWG2711">2711</a></td><td>path is convertible from approximately everything under the sun</td><td>Oulu</td><td>Complete</td></tr>
 	<tr><td><a href="http://wg21.link/LWG2716">2716</a></td><td>Specification of shuffle and sample disallows lvalue URNGs</td><td>Oulu</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2718">2718</a></td><td>Parallelism bug in [algorithms.parallel.exec] p2</td><td>Oulu</td><td></td></tr>
 	<tr><td><a href="http://wg21.link/LWG2719">2719</a></td><td>permissions function should not be noexcept due to narrow contract</td><td>Oulu</td><td>Complete</td></tr>




More information about the cfe-commits mailing list