0

このコードの場合

struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
    print(&f());
    print(&test());
}

gcc-4.6は、2つの「一時的な[-fpermissive]のアドレスの取得」エラーを発行します。これは4.6で導入され、gcc-4.5でコンパイルできました。

その理由はかなり明確で、十分に文書化されています。問題は、それがレガシーコードであり、コンパイルするには、それを機能させる必要があることです。したがって、ファイルやコードの一部の周りで#pragmasを実行して、-fpermissiveでコンパイルします。たとえば、顧客が既存のコードを変更しないことを固く決心しているとします(つまり、&f()または&test()を使用してprint()を呼び出すという事実は、一般的なソースファイルではなく変更できません)。言い換えれば、これ何らかの方法でコンパイルされ、唯一の選択肢は多かれ少なかれ苦痛です。

だから問題は-多くの場所で-fpermissiveを実行せずにそれを機能させるための可能な回避策はありますか?-Wフラグ、C++トリックなど。

4

4 に答える 4

4

つまり、&f()または&test()を使用してprint()を呼び出すという事実は変更できません。

タイプ自体を制御できる場合は、いつでも参照演算子、をオーバーロードして、そこからoperator&戻ることができthisます。一般的なケースで行うのは良いことではありませんが、正しいタイプの正しいポインタを返すことを考えると、かなり安全です。

基本クラスが含まれる場合、それはかなり複雑になります。仮想演算子のオーバーロードを使用する必要があり、階層内の各クラスはそれを個別に実装する必要があります。

于 2012-07-23T18:53:42.260 に答える
2

次のような追加のprintオーバーロードを作成することで、回避策を提供できconst&ます。

void print( test const & t ) {
   print(&t);             // Assuming that the function is 'print( test const * )'
                          // a print function should not take a non-const pointer!
}

そして、発信者を次のように変更します。

print( f() );

これにはコードの変更が必要ですが、形式が非常に限られているため、許容できる場合があります。また、注意してください

于 2012-07-23T18:23:31.477 に答える
2

コンパイラが文句を言わずに行っていたのとまったく同じようにコードを書き直してみませんか?つまり、一時的な(ただしアドレス可能な)変数に一時的なものを格納します。

struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
    test t1 = f();
    test t2 = test();
    print(&t1);
    print(&t2);
}

これは、古いコンパイラバージョンの場合と同じように動作するはずです。新しいコンパイラでは、コンパイラが暗黙的に実行していたことについて明示的にコードを変更する必要があることをお客様に伝えます。

于 2013-03-06T22:46:28.770 に答える
0

あなたが何をどれだけコントロールできるかは私にはわかりませんが、次のハックはうまくいくようです:

編集:元々f、コピーではなく参照を返していました。DeadMGは、一時が使用されるとすぐにこれが未定義の動作につながることを正しく指摘しているためf、コピーを返すように復元されます。

struct test {};
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
test f() { return test(); }
#define f() test_copy(f())
void print(const test *) {}
int main()
{
    print(&f());
    print(&test());
}

ハックは、基本的に一時的なものをconst参照に変換することです。これにより、コンパイラーはより幸せになります。一般に利用可能にするべきではありません。コンパイラをシャットダウンすることが唯一の目的です。ただし、顧客コードや提供されたAPIの根本的な問題を実際に解決するわけではありません。APIを修正し、特定の顧客のハックにのみ頼ることができます。

struct test {};
test f() { return test(); }
void print(const test &) {}

#define CUSTOMER_NEEDS_HACK
#ifdef CUSTOMER_NEEDS_HACK
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
#define f() test_copy(f())
void print(const test *t) { print(*t); }
#endif
于 2012-07-23T19:30:12.150 に答える