2

以下のコードは、Visual C++2005ではコンパイルされません。

class SomeClass {
public: boost::function<void()> func;
        SomeClass(boost::function<void()> &func): func(func) { }
};

void someFunc() {
    std::cout << "someFunc" << std::endl;
}

int main() {
    SomeClass sc(boost::function<void()>(&someFunc));
    sc.func(); // error C2228: left of '.func' must have class/struct/union
    return 0;
}

SomeClassコンストラクターの引数を括弧で囲んだり、引数リストの外にboost :: functionオブジェクトを作成したりすると、正常にコンパイルされます。

    SomeClass sc((boost::function<void()>(&someFunc)));
    // or
    boost::function<void()> f(&someFunc);
    SomeClass sc(f);

前のコードの問題は何ですか?

4

2 に答える 2

1

boost:function <void()>これは、aを参照し、を返す関数の関数宣言ですSomeClass。次のルールを覚えておくことができます。これは、他の多くのそのような曖昧性解消の場合に適用されることがわかります。これらのケースの説明8.2は、C++標準のセクションにあります。

宣言である可能性のある構成はすべて、宣言と見なされます

つまり、以下はパラメータ宣言として扱われ、括弧は不要になります

boost::function<void()>(&someFunc)

かっこを外すと明らかになります

boost::function<void()> &someFunc

したがって、宣言全体はもはやオブジェクトを宣言するのではなく、関数を宣言します

SomeClass sc(boost::function<void()> &someFunc);

これを修正するには、キャスト表記を使用します

SomeClass sc((boost::function<void()>)&someFunc);

または、あなたがしたように、式全体を括弧で囲みます。

これがすべての栄光のスタンダードです8.2

関数スタイルのキャストと6.8で述べた宣言との類似性から生じるあいまいさは、宣言のコンテキストでも発生する可能性があります。そのコンテキストでは、パラメーター名の前後に冗長な括弧のセットを使用した関数宣言と、初期化子として関数スタイルのキャストを使用したオブジェクト宣言のどちらかを選択します。6.8で述べたあいまいさの場合と同様に、解決策は、宣言である可能性のある構成を宣言と見なすことです。[注:宣言は、非関数スタイルのキャスト、初期化を示すa =、またはパラメーター名の前後の冗長な括弧を削除することによって、明示的に明確にすることができます。]

優先順位を制御するために、次のように、ほぼどこにでも括弧を導入できることに注意してください。

int (((((((a))))))) = 3;
int (*(pa)) = &a;
于 2009-06-14T12:53:08.970 に答える
0

これは「C++の最も厄介な解析」として知られています(ScottMeyersによるEffectiveSTLという本から)。

上で答えたように、コンパイラは問題のある行を関数宣言として解釈することを好みます。

于 2009-06-14T12:32:34.777 に答える