3

定数参照を期待する関数にポインターを渡すことに関して、奇妙な動作が見られます。明らかに、C++ は、参照を期待する関数にポインターを渡す前に、ポインターを参照することを期待しています。エラーまたは警告を探していますが、意味をなさない特定の条件が満たされない限り、エラーまたは警告が表示されません。

ポインターと参照の型は、C++ 17 標準バリアント (下記) です。私の C++17 バリアントのテンプレートにブール値が含まれている場合 (以下のように)、GCC8.3 はコードを正常にコンパイルします。しかし、予期しない実行結果があります。

標準バリアント テンプレートからブール値を削除すると、コードが期待どおりにコンパイルされません。違いはなぜですか?

#include <iostream>
#include <variant>
#include <stdint.h>

typedef std::variant <
        std::monostate,
        int8_t,
        int16_t,
        int32_t,
        int64_t,
        uint8_t,
        uint16_t,
        uint32_t,
        uint64_t,
        float,
        double
        ,bool //If bool is in the variant, the compiler compiles the code without error and understandably has UB. Why isn't the lack of de-reference bug in DoThing not caught when that is the case?
> StdVARIANT;

//if 'bool' is commented out of the variant the error (expected) is:
//invalid initialization of reference of type ‘const StdVARIANT&’

static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant);
static size_t DoThing(StdVARIANT* PtrToVariant);

static size_t DoThing(StdVARIANT* PtrToVariant){
    return GetIndexOfVariant(PtrToVariant); //this is a bug-PtrToVariant should be de referenced!
}

static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant){
    size_t Index = RefToVariant.index();
    return Index;
}

int main()
{
    StdVARIANT* myvar = new StdVARIANT();
    *myvar = (int32_t)1;
    std::cout<<"long: "<<std::get<int32_t>(*myvar)<<" "<<sizeof(std::get<int32_t>(*myvar))<<std::endl;
    *myvar = (double)2;
    std::cout<<"double: "<<std::get<double>(*myvar)<<" "<<sizeof(std::get<double>(*myvar))<<std::endl;
    std::cout<< myvar->index() << " " << DoThing(myvar)<<std::endl; //when 'bool' is in the std::variant, these two calls return different results (UB)
    delete myvar;
return 0;
}

上記のコード ブロックとしてコンパイルして実行します。

~/gcc-test$ g++ -std=c++17 -Wall -Wextra -pedantic main.cpp
~/gcc-test$ ./a.out
long: 1 4
double: 2 8
10 11

StdVARIANT から 'bool' をコメントアウトし、次のようにします。

~/gcc-test$ g++ -std=c++17 -Wall -Wextra -pedantic main.cpp
main.cpp: In function ‘size_t DoThing(StdVARIANT*)’:
main.cpp:27:30: error: invalid initialization of reference of type ‘const StdVARIANT&’ {aka ‘const std::variant<std::monostate, signed char, short int, int, long int, unsigned char, short unsigned int, unsigned int, long unsigned int, float, double>&’} from expression of type ‘StdVARIANT*’ {aka ‘std::variant<std::monostate, signed char, short int, int, long int, unsigned char, short unsigned int, unsigned int, long unsigned int, float, double>*’}
     return GetIndexOfVariant(PtrToVariant); //this is a bug-PtrToVariant should be de referenced!
                              ^~~~~~~~~~~~
main.cpp:23:15: note: in passing argument 1 of ‘size_t GetIndexOfVariant(const StdVARIANT&)’
 static size_t GetIndexOfVariant(const StdVARIANT& RefToVariant);
               ^~~~~~~~~~~~~~~~~

bool がコメントアウトされたときだけでなく、常にエラーが発生しないのはなぜですか?

4

1 に答える 1