2016-06-20 9 views
8

Ich bemerkte, dass libstdC++ die Implementierung von std::ignore ein const T& Argument, das nicht an einen flüchtigen rvalue binden kann. Daher schlägt der folgende Code zu kompilieren:Ist libstdC++ falsch, um die Zuweisung von flüchtigem rvalue zu std :: ignore abzulehnen?

#include <tuple> 
#include <utility> 
struct C {}; 
using VC = C volatile; 
int main() { 
    std::tuple<VC> t; 
    std::tie(std::ignore) = std::move(t); 
} 

(http://coliru.stacked-crooked.com/a/7bfc499c1748e59e)

Ist dies eine Verletzung der Norm, oder gibt es eine Klausel, die dieses nicht definiertes Verhalten macht?

+0

Warum würden Sie verwenden möchten 'volatile' in erster Linie? Es deaktiviert Optimierungen, macht die Dinge nicht sicher. Ich sehe nicht, warum du das tust ... –

+1

@JesperJuhl * weil es da ist * – Brian

+0

Kein guter Grund. Code kann geändert werden. –

Antwort

0

Ich bin kein Sprachanwalt, also werde ich diese Frage so direkt wie möglich beantworten.

// [tuple.creation], tuple creation functions: 
const unspecified ignore; 

Wie Sie bemerkt haben, die libstdc++ Implementierung definiert ignore wie folgt aus:: es

// A class (and instance) which can be used in 'tie' when an element 
    // of a tuple is not required 
    struct _Swallow_assign 
    { 
    template<class _Tp> 
     const _Swallow_assign& 
     operator=(const _Tp&) const 
     { return *this; } 
    }; 

Während die libc++ Version definiert wie

ignore in der Synopse von tuple in tuple.general als solche gefunden wird dies:

template <class _Up> 
struct __ignore_t 
{ 
    template <class _Tp> 
     _LIBCPP_INLINE_VISIBILITY 
     const __ignore_t& operator=(_Tp&&) const {return *this;} 
}; 

Als solche kompiliert es in libC++. Nun ist die Definition von std::tie in [tuple.creation] zu finden, die sagt:

Returns: tuple<Types&...>(t...). Wenn ein Argument in t ignore ist, hat das Zuweisen eines beliebigen Werts zum entsprechenden Tupelelement keinen Effekt.

sagen Dies nichts über ignore selbst, so dass ich dies zu nicht spezifiziert Verhalten gehen ankreiden. Sie können argumentieren, es ist undefined Verhalten durch Auslassung, aber das könnte es dehnen.

+1

Ich bin mir nicht sicher, ob ich das verstehe.Gibt das nicht das Verhalten so gut an, dass der Code, den ich gepostet habe, * keinen Effekt * haben sollte, was der Implementierungslizenz nicht den Anschein gibt, den Code abzulehnen? – Brian

+0

@Brian * Kein Effekt * ist an sich zu niedrig angegeben. 'std :: tie' hat keine * effects * -Klausel. Der 'operator =' in 'ignore' macht nichts als' return * this', also ist ein no-op, was genau unter eine Definition von * no effects * passt. In beiden Fällen wird der Code wegen der Implementierung der Bibliothek abgelehnt, nicht wegen einer Verletzung der Klauseln unter "std :: tie". –

+0

Nein, es heißt nicht, dass die Funktion 'std :: tie' keine Auswirkungen hat; es besagt, dass "das Zuweisen eines Wertes zu dem entsprechenden Tupel-Element keine Auswirkung hat". – Brian

0

Kommentar:

// g++ 4.8.4 
int main() { 
    volatile int vi; 
    std::ignore = vi; 

    // error: no match for ‘operator=’ (
    //  operand types are ‘const std::_Swallow_assign’ 
    //  and ‘std::remove_reference<volatile int&>::type {aka volatile int}’ 
    //) 
    // std::ignore = std::move(vi); 

    // However this compiles: 
    volatile int&& vir = std::move(vi); 
    std::ignore = vir; 
} 
+0

Hmm interessant ... –