Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are is_swappable and is_nothrow_swappable not included in C++11?

I was surprised to discover that is_swappable<T> and is_nothrow_swappable<T> are not among the new C++11 type_traits metafunctions. They are very useful for propagating noexcept for templates and for determining whether it is possible to implement a non-throwing swap for a template.

libc++ rolls its own internal versions: see __is_swappable and __is_nothrow_swappable in its version of type_traits, and it makes extensive internal use of them but does not make them available outside the library.

I ended up cobbling together my own version of these for a personal project, which seem to work but I'm sure its broken somehow.

I am curious about the absence of these two as they seem quite important. Was this feature considered during the C++11 standardization process, or was it just an oversight that it was not included? If it was considered, what lead to it not being incorporated into the final standard (lack of time, implementation issues, etc.)? Is there a defect report or evolution paper discussing this? Any plans to incorporate these traits in C++1Y? Is there an acknowledged 'correct' version somewhere?

like image 796
acm Avatar asked Jan 23 '13 15:01

acm


1 Answers

is_swappable<T> and is_nothrow_swappable<T> were never proposed for C++11. That is the main reason they aren't in C++11. I.e. nothing gets in without being proposed.

So why weren't these proposed?

Speaking from personal experience, I don't propose anything that I haven't implemented and found useful. And though I did implement them for libc++, I did not do so prior to C++11 being published. I simply did not have the time and tools to do so for C++11. My best guess is that this was true of any one else.

Glad you found these useful. You could be the one to propose them for the next C++ standard! Seriously! We need your help!

Update

In response to:

it's a bit of a hack though, because this is only works if swap is implemented in terms of the Move Constructors and Assignment Operators

Here's test indicating how it behaves on libc++'s implementation:

#include <type_traits>
#include <iostream>

struct A
{
    A(const A&);
};

struct B
{
};

void swap(B&, B&);

struct C
{
};

void swap(C&, C&) noexcept;

struct D
{
    D(const D&) noexcept;
    D& operator=(const D&) noexcept;
};

int main()
{
    std::cout << "std::__is_nothrow_swappable<int>::value = "
              << std::__is_nothrow_swappable<int>::value << '\n';
    std::cout << "std::__is_nothrow_swappable<A>::value = "
              << std::__is_nothrow_swappable<A>::value << '\n';
    std::cout << "std::__is_nothrow_swappable<B>::value = "
              << std::__is_nothrow_swappable<B>::value << '\n';
    std::cout << "std::__is_nothrow_swappable<C>::value = "
              << std::__is_nothrow_swappable<C>::value << '\n';
    std::cout << "std::__is_nothrow_swappable<D>::value = "
              << std::__is_nothrow_swappable<D>::value << '\n';
}

Which for me outputs:

std::__is_nothrow_swappable<int>::value = 1
std::__is_nothrow_swappable<A>::value = 0
std::__is_nothrow_swappable<B>::value = 0
std::__is_nothrow_swappable<C>::value = 1
std::__is_nothrow_swappable<D>::value = 1
like image 153
Howard Hinnant Avatar answered Sep 24 '22 23:09

Howard Hinnant