template<class _Callable>
_LIBCPP_INLINE_VISIBILITY
-void call_once(once_flag&, _Callable);
+void call_once(once_flag&, _Callable&);
+
+template<class _Callable>
+_LIBCPP_INLINE_VISIBILITY
+void call_once(once_flag&, const _Callable&);
#endif // _LIBCPP_HAS_NO_VARIADICS
#else // _LIBCPP_HAS_NO_VARIADICS
template<class _Callable>
friend
- void call_once(once_flag&, _Callable);
+ void call_once(once_flag&, _Callable&);
+
+ template<class _Callable>
+ friend
+ void call_once(once_flag&, const _Callable&);
#endif // _LIBCPP_HAS_NO_VARIADICS
};
template <class _Fp>
class __call_once_param
{
- _Fp __f_;
+ _Fp& __f_;
public:
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
_LIBCPP_INLINE_VISIBILITY
- explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
-#else
- _LIBCPP_INLINE_VISIBILITY
- explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
-#endif
+ explicit __call_once_param(_Fp& __f) : __f_(__f) {}
_LIBCPP_INLINE_VISIBILITY
void operator()()
_LIBCPP_INLINE_VISIBILITY
void __execute(__tuple_indices<_Indices...>)
{
- __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...);
+ __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
}
};
template <class _Fp>
class __call_once_param
{
- _Fp __f_;
+ _Fp& __f_;
public:
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
- _LIBCPP_INLINE_VISIBILITY
- explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
-#else
_LIBCPP_INLINE_VISIBILITY
- explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
-#endif
+ explicit __call_once_param(_Fp& __f) : __f_(__f) {}
_LIBCPP_INLINE_VISIBILITY
void operator()()
{
if (__flag.__state_ != ~0ul)
{
- typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::type...> _Gp;
- __call_once_param<_Gp> __p(_Gp(__decay_copy(_VSTD::forward<_Callable>(__func)),
- __decay_copy(_VSTD::forward<_Args>(__args))...));
+ typedef tuple<_Callable&&, _Args&&...> _Gp;
+ _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
+ __call_once_param<_Gp> __p(__f);
__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
}
}
template<class _Callable>
inline _LIBCPP_INLINE_VISIBILITY
void
-call_once(once_flag& __flag, _Callable __func)
+call_once(once_flag& __flag, _Callable& __func)
{
if (__flag.__state_ != ~0ul)
{
}
}
+template<class _Callable>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+call_once(once_flag& __flag, const _Callable& __func)
+{
+ if (__flag.__state_ != ~0ul)
+ {
+ __call_once_param<const _Callable> __p(__func);
+ __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
+ }
+}
+
#endif // _LIBCPP_HAS_NO_VARIADICS
_LIBCPP_END_NAMESPACE_STD
// struct once_flag;
// template<class Callable, class ...Args>
-// void call_once(once_flag& flag, Callable func, Args&&... args);
+// void call_once(once_flag& flag, Callable&& func, Args&&... args);
#include <mutex>
#include <thread>
}
};
+class NonCopyable
+{
+#if !defined(__clang__)
+ // GCC 4.8 complains about the following being private
+public:
+ NonCopyable(const NonCopyable&)
+ {
+ }
+#else
+ NonCopyable(const NonCopyable&);
+#endif
+public:
+ NonCopyable() {}
+
+ void operator()(int&) {}
+};
+
+#if __cplusplus >= 201103L
+// reference qualifiers on functions are a C++11 extension
+struct RefQual
+{
+ int lv_called, rv_called;
+
+ RefQual() : lv_called(0), rv_called(0) {}
+
+ void operator()() & { ++lv_called; }
+ void operator()() && { ++rv_called; }
+};
+#endif
#endif
int main()
std::once_flag f;
std::call_once(f, MoveOnly(), MoveOnly());
}
+ // check LWG2442: call_once() shouldn't DECAY_COPY()
+ {
+ std::once_flag f;
+ int i = 0;
+ std::call_once(f, NonCopyable(), i);
+ }
+#if __cplusplus >= 201103L
+// reference qualifiers on functions are a C++11 extension
+ {
+ std::once_flag f1, f2;
+ RefQual rq;
+ std::call_once(f1, rq);
+ assert(rq.lv_called == 1);
+ std::call_once(f2, std::move(rq));
+ assert(rq.rv_called == 1);
+ }
+#endif
#endif // _LIBCPP_HAS_NO_VARIADICS
}
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2438">2438</td><td>std::iterator inheritance shouldn't be mandated</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2439">2439</td><td>unique_copy() sometimes can't fall back to reading its output</td><td>Lenexa</td><td></td></tr>
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2440">2440</td><td>seed_seq::size() should be noexcept</td><td>Lenexa</td><td>Complete</td></tr>
- <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442">2442</td><td>call_once() shouldn't DECAY_COPY()</td><td>Lenexa</td><td></td></tr>
+ <tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442">2442</td><td>call_once() shouldn't DECAY_COPY()</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2448">2448</td><td>Non-normative Container destructor specification</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2454">2454</td><td>Add raw_storage_iterator::base() member</td><td>Lenexa</td><td>Complete</td></tr>
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2455">2455</td><td>Allocator default construction should be allowed to throw</td><td>Lenexa</td><td>Complete</td></tr>