2014-11-07 98 views
20

Ho il seguente frammento di codice:Perché lo swapping di array multidimensionali non è nullo?

#include <algorithm> 
#include <iostream> 

int main(int argc, char** argv) { 
    int x[2][3]; 
    int y[2][3]; 

    using std::swap; 
    std::cout << noexcept(swap(x, y)) << "\n"; 

    return 0; 
} 

Utilizzando GCC 4.9.0, Questo stampa 0. Non capisco perché.

Secondo lo standard ci sono due overload per std::swap:

namespace std { 
    template<class T> void swap(T& a, T& b) noexcept(
     is_nothrow_move_constructible<T>::value && 
     is_nothrow_move_assignable<T>::value 
    ); 

    template<class T, size_t N> 
    void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))); 
} 

Nella mia comprensione l'identificatore noexcept per l'array dovrebbe funzionare in modo ricorsivo per gli array multidimensionali.

Perché lo swapping di array multidimensionali non è noexcept?


Durante il tentativo di trovare un esempio minimo che si comporta ancora stranamente mi si avvicinò con il seguente:

#include <iostream> 

template<class T> struct Specialized  : std::false_type {}; 
template<>  struct Specialized<int> : std::true_type {}; 

template<class T>    void f(T& a) noexcept(Specialized<T>::value); 
template<class T, std::size_t N> void f(T (&a)[N]) noexcept(noexcept(f(*a))); 

int main(int argc, char** argv) { 
    int x, y[1], z[1][1]; 

    std::cout << noexcept(f(x)) << " " 
       << noexcept(f(y)) << " " 
       << noexcept(f(z)) << "\n"; 
} 

Utilizzando GCC 4.9.0 viene stampato 1 1 0, ma ancora una volta non capisco perché.

+1

[clang say 1] (http://coliru.stacked-crooked.com/a/9d1c1e7307dda039) –

+0

Sembra molto strano per me. Ho trovato [DR 809] (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809) che [appare] (https://gcc.gnu.org/ onlinedocs/gcc-4.9.0/libstdC++/api/a01316_source.html # l00185) per essere [implementato] (https://gcc.gnu.org/onlinedocs/libstdc++/manual/bugs.html) in libstdC++ quindi forse l'errore si trova altrove. Per la tua ultima modifica, [clang] (http://coliru.stacked-crooked.com/a/79dd288d30d8f159) stampa anche '1 1 0'. clang con libC++ stampa '0' per lo snippet originale. –

+0

[Coliru] (http://coliru.stacked-crooked.com/a/7fa0b200e56d1bd4), [2] (http://coliru.stacked-crooked.com/a/485e10b802dd3a96) –

risposta

11

Questo sovraccarico:

template<class T, size_t N> 
void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))); 

non è portata fino ;, quindi swap(*a, *b) non considera questo sovraccarico. Questo è causa di:

3.3.2/1 Il punto della dichiarazione per un nome è subito dopo la sua completa dichiaratore (clausola 8) e prima della sua inizializzazione (se presente) ...

e la le specifiche delle eccezioni fanno parte del dichiaratore.

+3

Questa sembra una supervisione piuttosto seria nello standard. Nella sua forma attuale le dichiarazioni "noxcept" ricorsive ingenue non funzionano. Peggio ancora, lo stesso standard usa queste dichiarazioni ingenue ricorsive. – orlp

+5

Dillo a Babbo Natale; metterà Bjarne nella lista cattiva. – rightfold

+0

Questo è un difetto noto. Vedi [LWG2456] (http://wg21.cmeerw.net/lwg/issue2456). – FrankHB