如何编写启用ADL的追踪返回types或noexcept规范?

想象一下,我正在写一些容器模板什么的。 而现在是专门为它的std::swap 。 作为一个好公民,我将通过做这样的事情来启用ADL:

 template <typename T> void swap(my_template<T>& x, my_template<T>& y) { using std::swap; swap(x.something_that_is_a_T, y.something_that_is_a_T); } 

这非常整齐。 直到我想添加一个exception规范。 只要T swapnoexcept ,我的swap就是noexcept noexcept 。 所以,我会写这样的:

 template <typename T> void swap(my_template<T>& x, my_template<T>& y) noexcept(noexcept(swap(std::declval<T>(), std::declval<T>()))) 

问题是,在那里swap需要ADL发现swapstd::swap 。 我该如何处理?

我想我会把它移动到一个单独的命名空间

 namespace tricks { using std::swap; template <typename T, typename U> void swap(T &t, U &u) noexcept(noexcept(swap(t, u))); } template <typename T> void swap(my_template<T>& x, my_template<T>& y) noexcept(noexcept(tricks::swap(std::declval<T>(), std::declval<T>()))) { using std::swap; swap(x.something_that_is_a_T, y.something_that_is_a_T); } 

或者,您可以将整个代码转换为tricks并委派给那里。

返回types有一个类似的问题 :

 // Want to be compatible with both boost::tuple and std::tuple template<typename Tuple> auto first(Tuple&& tuple) -> /* ??? */ { // Introduce name into scope using std::get; // but ADL can still pick boost::get for boost::tuple return get<0>(std::forward<Tuple>(tuple)); } 

使用decltype( get<0>(std::forward<Tuple>(tuple)) )不正确,因为get不在范围内。

可能的解决方法是:

  • 在封闭范围内引入一个虚拟模板(在我的例子中, swap你的情况) 这包括将using std::swap声明放在封闭的名称空间中,其缺点是污染了名称空间。

  • 在我的例子中,使用了一个types特征: typename std::tuple_element<0, typename std::remove_reference<Tuple>::type>::type (实际上这个是有问题的,但是不属于这里的原因)一个潜在的is_nothrow_swappable<T>::value在你的情况。 然后专业化可以让模板扩展到其他types,如果需要的话。

而不是声明但不定义一个似乎可能导致混淆的函数模板,我会写我自己的types特征(无论如何,这应该是标准库中的东西)。 在标准库的引导下,我将定义如下的内容:

 #include <type_traits> #include <utility> namespace adl { using std::swap; template<typename T, typename U> struct is_nothrow_swappable : std::integral_constant< bool, noexcept(swap(std::declval<T &>(), std::declval<U &>())) > { }; } // namespace adl 

我们必须定义自己的命名空间,以将std :: swap导入(以避免将其分发给每个人),但是当然,如​​果它在标准库中,则不必要,因为它们已经可以进行非限定的调用交换。

C ++ 17已经用std :: is_nothrow_swappable解决了这个特殊的用例: http ://en.cppreference.com/w/cpp/types/is_swappable

Interesting Posts