2016-06-20 16 views
8

Bu libstdC++ uygulamasının std::ignore numaralı uygulamasının, bir uçucu rıhtıya bağlanamayan bir const T& argümanını aldığını fark ettim. Böylece, aşağıdaki kod derlenmeyecektir:Std :: ignore için volatile rvalue atama reddetmek için libstdC++ yanlış mı?

#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)

bu standart ihlal mı veya bu tanımsız davranış hale getiren bir madde bulunmamaktadır?

+0

Neden ilk etapta 'volatile' kullanmak isteyeyim? Optimizasyonları devre dışı bırakır, iş parçacığını güvenli hale getirmez. Bunu neden yaptığını anlamıyorum ... –

+1

@JesperJuhl * çünkü orada * – Brian

+0

İyi bir sebep değil. Kod değiştirilebilir. –

cevap

0

Dil avukatı değilim, bu yüzden bu soruyu olabildiğince doğrudan yanıtlayacağım.

ignore

gibi tuple.general içinde tuple arasında özet bulunur:

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

Fark gibi, libstdc++ uygulama aşağıdaki gibi ignore tanımlar: libc++ versiyonu gibi tanımlar

// 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; } 
    }; 

Oysa Bu:

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

Bu şekilde, libC++ derler. Şimdi std::tie tanımı [tuple.creation] bulunabilir diyor ki:

İade: tuple<Types&...>(t...). t'daki bir argüman ignore olduğunda, ilgili tuple elemanına herhangi bir değer atamak etkisizdir.

Bu ignore kendisi hakkında hiçbir şey söylemez, bu yüzden belirtilmemiş davranışa bu kadar tebeşir gidiyorum. undefined davranışını ihmal ederek tartışabilirsiniz, ancak bu onu genişletiyor olabilir.

+1

Anladığımdan emin değilim.Davranış kuralını yeterince iyi tanımlamamaktadır, böylece gönderdiğim kodun, kodu reddetmek için uygulama lisansı vermediği * etkisiz * olması gerekir. – Brian

+0

@Brian * Etki yok * kendi içinde az belirtilmiş. std :: tie', * efektleri içermez. '' Ignore''da 'operator =' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'bir şey yapmaz. Her iki şekilde de, kod, std :: tie' altındaki tüm dillerden herhangi birinin ihlali nedeniyle değil, kütüphanenin nasıl uygulandığından dolayı reddedilir. –

+0

Hayır, 'std :: tie' işlevinin hiçbir etkisi olmadığını; "karşılık gelen tuple elemanına herhangi bir değer atamanın bir etkisi yoktur" der. – Brian

0

Yorum:

// 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 ilginç ... –