3

私は次のことを行おうとしています。関数内でローカルに定義されたクラスからメンバー関数のアドレスを取得します。

class ConnectionBase
{
};

template class<EventType, SinkType>
class ConnectionImpl : public ConnectionBase
{
public:
typedef void (SinkType::*EventCallback)(EventType const&);
};


template<class EventType>
class Source
{
    template <class SinkType>
    boost::shared_ptr<ConnectionBase> setupCallback(typename ConnectionImpl<EventType, SinkType>::EventCallback func, SinkType* sink)
    {
    // do the actual connecting.
    }
};

class SomeClass
{
public:
    void someFunction(int const& event){}
}

class SomeUnitTest
{
public:
    void someTest()
    {
        class NestedClass 
        {
        public:
            void someFunction(int const& event){}
        };

       NestedClass nc;

       //Try#1 - This does not work
       setupCallback<int, NestedClass>(&NestedClass::someFunction, &nc);

       //Try #2 - This also does not work
       setupCallback<int, NestedClass>(&SomeUnitTest::someTest::NestedClass::someFunction, &nc);

       //Try #3 - Following the GCC error output, I tried this
       setupCallback<int, NestedClass>(&SomeUnitTest::someTest()::NestedClass::someFunction, &nc);

       SomeClass sc;

       //This works fine, as expected
       setupCallback<int, SomeClass>(&SomeClass::someFunction, &sc);

    }
};

#2と#3を試してみてください。GCCを完全に混乱させます。私が何をしようとしているのかわかりません。試行#1は、「setupCallback(void(SomeUnitTest :: someTest():: NestedClass :: SomeFunction :: *)など)の形式のsetupCallbackが存在しないことを示す、より役立つエラーメッセージを生成します。これが試行#3の誕生です。

関数内で定義されたクラスに関する多くの情報を実際に見つけることができません。誰かがこれの正しい構文を知っていますか、そしておそらくこのトピックを議論するリソースを持っていますか?

両方のポスターが指摘しているように、これは解決されたようです。ローカルクラスにはリンクがなく、機能しません。これを知った今、この問題に遭遇し、この質問に遭遇した他の人のために、これについて説明しているこの記事を見つけました:http: //www.informit.com/guides/content.aspx? g=cplusplus&seqNum=420

編集:setupCallback()の明確化、より通常のクラスでの作業例
編集#2:「ネストされた」を「ローカル」に変更するように文言を更新しました。setupCallbackの詳細を追加しました。
編集#3:詳細情報へのリンクを追加しました。みんな、ありがとう。

4

2 に答える 2

4

構文の問題についてはわかりません。通常のアクセス規則が適用されるはずですが、これらのメンバー関数にはリンケージがないため、それが機能する場合は別の問題があります。
ローカル型を受け入れるにsetupCallback()は、テンプレート関数である必要がありますが、リンケージのないテンプレート型引数は許可されていません。

§3.5/8は次のように述べています。

これらの規則でカバーされていない名前には関連性がありません。さらに、注記されている場合を除き、ローカル スコープ (3.3.2) で宣言された名前にはリンケージがありません。

ローカル クラスのメンバーは対象外です。§9.3/3は次のことを明確にしています。

ローカル クラス (9.8) のメンバー関数にはリンケージがありません。

簡単に言えば、ローカル クラスのメンバー関数をコールバックとして使用しないでください。代わりに非ローカル クラスを使用してください。

于 2010-01-28T07:20:32.413 に答える
4

住所を取得するという特定の問題が考慮されている限り、最初のバリアントは正しいものです。ローカル クラスのメンバー関数のアドレスの取得に制限はありません。適切な構文は通常の

&NestedClass::someFunction

それだけです。コードの中間ポインターに保存してみることができます

void (NestedClass::*ptr)() = &NestedClass::someFunction;

コンパイラがそれを受け入れると確信しています。

ただし、コードに存在すると思われる問題は、メンバー関数のアドレスを取得する適切な方法とはまったく関係ありません。setupCallbackの最初のパラメーターが宣言される方法についてです。あなたはそれ&SomeClass::someFunctionが最初の引数として機能すると言うので、私は次のsetupCallbackように宣言されることを期待しています

void setupCallback(void (SomeClass::*cb)(), SomeClass *p); // one possibility

つまり、特定のメンバーへのポインターを期待するようにハードコーディングさSomeClassれています。代わりにのメンバーへのポインターを指定することはできませんNestedClassNestedClassは とはまったく関係がなく、 のメンバーへSomeClassのポインターは のメンバーへのポインターとNestedClass完全に互換性がありませんSomeClass。これがコンパイルされない理由です。

あなたが私たちに見せていないものがない限り(おそらく関数テンプレートであるか、または異なるパラメータタイプに対してオーバーロードされているかなど)、あなたがしようとしていることは、関係がないsetupCallback限り、メンバーアドレスの取得方法に関係なく達成することは不可能です.NestedClassSomeClass。FunctionはandのみでsetupCallback動作するように設計されています。SomeClassSomeClass

に関する詳細情報を提供しますsetupCallback。それはどのように宣言されていますか?

setupCallbackがクラス型でパラメータ化された関数テンプレートとして宣言されている場合、次のように注意してください。

template <class T> void setupCallback(void (T::*cb)(), T* p);

NestedClassローカル クラスを parameter のテンプレート引数として使用することはできませんT。この場合、NestedClassリンクがないという事実が実際に作用します。しかし、繰り返しになりますが、これはメンバー アドレスの取得とは関係なく、リンケージのないクラスは C++ のテンプレート引数として使用できないという事実が原因です。

于 2010-01-28T07:47:10.497 に答える