Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Unie i niezdefiniowane zachowanie w C++17

Ostatnio zmodyfikowano 2018-03-15 20:21
Autor Wiadomość
pekfos
» 2018-03-14 00:46:11
Inaczej: Ja takiej reguły nie znalazłem, szukając w sensownych miejscach, jak [class.union], czy [basic.life]. Być może takiej reguły nie ma, wtedy [defns.undefined]:
Undefined behavior may be expected when this document omits any explicit definition of behavior
Choć i tak istniejące ogólne reguły mówią, że zachowanie jest niezdefiniowane. Podejrzewam, że mógłbyś zadać takie precyzyjne pytanie autorytetom języka. Uzyskanie odpowiedzi nie musiało znaczyć, że ktoś poświęcił dość czasu by wiedzieć, co dokładnie miałeś na myśli w swoim pytaniu.
P-170001
luks
Temat założony przez niniejszego użytkownika
» 2018-03-14 16:26:13
Boże...
P-170003
luks
Temat założony przez niniejszego użytkownika
» 2018-03-14 16:35:12
Jeżeli ktoś ma namiary na dokumenty do GCC, Clang lub Visual C++, w których są dokładnie opisane rozszerzenia języka C++ w danym kompilatorze, to proszę o odnośniki.
P-170004
pekfos
» 2018-03-14 17:18:18
P-170007
jankowalski25
» 2018-03-14 20:42:35
Chcesz grzebać w rozszerzeniach kompilatora? Może inaczej: jaki konkretnie problem chcesz rozwiązać? Może dałoby się inaczej napisać kod tak, aby nie używać unii i uzyskać coś przenośnego? Pisanie kodu pod konkretny kompilator ma sens chyba tylko wtedy, gdy inne rozwiązanie nie istnieje lub chodzi o utworzenie czegoś przenośnego, co siłą rzeczy prędzej czy później musi opierać się na czymś konkretnym (ale wtedy w razie problemów wystarczy podmienić implementację nieprzenośnych kawałków i przekompilować całość, a nie przepisywać wszystko na nowo).
P-170017
luks
Temat założony przez niniejszego użytkownika
» 2018-03-15 00:16:00
To chcę osiągnąć:

C/C++
#include<iostream>
#include<string>
#include<type_traits>
#include<memory>

struct Array2 {
    float data[ 2 ];
   
    constexpr Array2( float e0, float e1 ) noexcept
        : data
    { e0, e1 } {
    }
   
    constexpr float & operator []( int index ) noexcept {
        return data[ index ];
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return data[ index ];
    }
};

struct Vec2Elements
    : public Array2
{
    using Array2::Array2;
};

inline std::ostream & operator <<( std::ostream & os, Vec2Elements const & elements ) {
    return os << '[' << elements[ 0 ] << ", " << elements[ 1 ] << ']';
}

struct X
    : public Array2
{
    X * operator &() = delete;
   
    constexpr X & operator =( float other ) noexcept {
        data[ 0 ] = other;
        return * this;
    }
   
    constexpr operator float() noexcept {
        return data[ 0 ];
    }
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 0 ], data[ 0 ] };
    }
};

inline std::ostream & operator <<( std::ostream & os, X const & x ) {
    return os << x[ 0 ];
}

struct Y
    : public Array2
{
    static constexpr int indexMap[] { 1 };
   
    Y * operator &() = delete;
   
    constexpr Y & operator =( float other ) noexcept {
        data[ 1 ] = other;
        return * this;
    }
   
    constexpr operator float() noexcept {
        return data[ 1 ];
    }
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 1 ], data[ 1 ] };
    }
   
    constexpr float & operator []( int index ) noexcept {
        return data[ indexMap[ index ] ];
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return data[ indexMap[ index ] ];
    }
};

inline std::ostream & operator <<( std::ostream & os, Y const & y ) {
    return os << y[ 0 ];
}

struct XX
    : public Array2
{
    static constexpr int indexMap[] { 0, 0 };
   
    XX * operator &() = delete;
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 0 ], data[ 0 ] };
    }
   
    constexpr float & operator []( int index ) noexcept {
        return data[ indexMap[ index ] ];
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return data[ indexMap[ index ] ];
    }
};

struct YY
    : public Array2
{
    static constexpr int indexMap[] { 1, 1 };
   
    YY * operator &() = delete;
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 1 ], data[ 1 ] };
    }
   
    constexpr float & operator []( int index ) noexcept {
        return data[ indexMap[ index ] ];
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return data[ indexMap[ index ] ];
    }
};

struct XY
    : public Array2
{
    using Array2::Array2;
   
    XY * operator &() = delete;
   
    constexpr XY & operator =( Vec2Elements const & other ) noexcept {
        data[ 0 ] = other[ 0 ];
        data[ 1 ] = other[ 1 ];
        return * this;
    }
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 0 ], data[ 1 ] };
    }
};

struct YX
    : public Array2
{
    static constexpr int indexMap[] { 1, 0 };
   
    YX * operator &() = delete;
   
    constexpr YX & operator =( Vec2Elements const & other ) noexcept {
        data[ 1 ] = other[ 0 ];
        data[ 0 ] = other[ 1 ];
        return * this;
    }
   
    constexpr operator Vec2Elements() noexcept {
        return { data[ 1 ], data[ 0 ] };
    }
   
    constexpr float & operator []( int index ) noexcept {
        return data[ indexMap[ index ] ];
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return data[ indexMap[ index ] ];
    }
};

struct Vec2 {
    union {
        X x;
        Y y;
       
        X s;
        Y t;
       
        X u;
        Y v;
       
        XX xx;
        XX ss;
        XX uu;
       
        YY yy;
        YY tt;
        YY vv;
       
        XY xy;
        XY st;
        XY uv;
       
        YX yx;
        YX ts;
        YX vu;
    };
   
    Vec2() {
    }
   
    constexpr Vec2( float xy_ ) noexcept
        : xy
    { xy_, xy_ } {
    }
   
    constexpr Vec2( float x_, float y_ ) noexcept
        : xy
    { x_, y_ } {
    }
   
    constexpr Vec2( Vec2Elements const & other ) noexcept
        : xy
    { other[ 0 ], other[ 1 ] } {
    }
   
    constexpr Vec2 & operator =( Vec2Elements const & other ) noexcept {
        x = other[ 0 ];
        y = other[ 1 ];
        return * this;
    }
   
    constexpr float & operator []( int index ) noexcept {
        return *( std::addressof( x[ 0 ] ) + index );
    }
   
    constexpr float const & operator []( int index ) const noexcept {
        return *( std::addressof( x[ 0 ] ) + index );
    }
};

inline std::ostream & operator <<( std::ostream & os, Vec2 const & vec ) {
    return os << '[' << vec[ 0 ] << ", " << vec[ 1 ] << ']';
}

int main() {
    Vec2 val2;
    val2.x = 3.5f;
    val2.y = 4.5f;
    val2.yx = val2.xy;
    std::cout << val2 << '\n';
    std::cout << val2.x << '\n';
    std::cout << val2.x[ 0 ] << '\n';
    std::cout << val2.y << '\n';
    std::cout << val2.y[ 0 ] << '\n';
    std::cout << val2[ 0 ] << '\n';
    std::cout << val2[ 1 ] << '\n';
    std::cout << val2.xx << '\n';
    std::cout << val2.xx[ 0 ] << '\n';
    std::cout << val2.xx[ 1 ] << '\n';
    std::cout << val2.xy << '\n';
    std::cout << val2.xy[ 0 ] << '\n';
    std::cout << val2.xy[ 1 ] << '\n';
    std::cout << val2.yx << '\n';
    std::cout << val2.yx[ 0 ] << '\n';
    std::cout << val2.yx[ 1 ] << '\n';
    std::cout << val2.yy << '\n';
    std::cout << val2.yy[ 0 ] << '\n';
    std::cout << val2.yy[ 1 ] << '\n';
   
    return 0;
}
P-170019
pekfos
» 2018-03-15 00:31:55
C/C++
return *( std::addressof( x[ 0 ] ) + index );
To co innego, niż to o co wcześniej pytałeś. x[0] to wywołanie metody - w tym momencie x musi być aktywną składową unii, inaczej jest to niezdefiniowane zachowanie ([basic.life]/7.2). Wyjątek dla CIS nie dotyczy tego przypadku.
P-170020
luks
Temat założony przez niniejszego użytkownika
» 2018-03-15 01:01:29
Nie-sa-mo-wi-te! A teraz pytam, czy można uzyskać takie API w C++17 bez UB. Bądź czujny, bo jutro mogę ponownie zapytać o coś innego.
P-170021
1 2 « 3 » 4
Poprzednia strona Strona 3 z 4 Następna strona