如何获取函数中定义的本地类的成员函数的地址(C++)

发布于 2024-08-20 03:04:11 字数 2050 浏览 2 评论 0原文

我正在尝试执行以下操作:从函数中本地定义的类获取成员函数的地址。

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,其格式为“setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc) 这就是尝试#3 的诞生。

我真的找不到关于函数内定义的类的大量信息,有人知道正确的语法吗?也许有讨论这个主题的资源?

好吧,看来这已经解决了,正如两位海报所指出的那样,本地类没有链接,它无法工作。现在知道了这一点,我发现这篇文章讨论了这个问题,对于遇到这个问题并偶然发现这个问题的其他人: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=420

编辑: setupCallback() 的说明,使用更常规的类的工作示例
编辑#2: 更新了措辞,将“嵌套”更改为“本地”。添加了 setupCallback 的更多详细信息。
编辑#3:添加了更多信息的链接。谢谢大家。

I am trying to do the following: Obtain the address of a member function from a class that was locally defined within a function.

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);

    }
};

Try #2 and #3 utterly confuse GCC, it has no idea what I am trying to do.
Try #1 produces a more helpful error message saying no setupCallback exists that takes the form "setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc)
Which is how try #3 was born.

I can't really find a lot of information about classes defined inside a function, does anyone know the correct syntax for this, and maybe have a resource that discusses this topic?

Ok, it appears this is settled, as both posters have pointed out, local classes have no linkage, it can't work. Now knowing this, I found this article that discusses this, for anyone else that runs into this problem and stumbles across this question: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=420

Edit:
Clarification of setupCallback(), working example with a more regular class
Edit #2:
Updated wording to change "nested" to "local". Added more detail for setupCallback.
Edit #3: Added links to furhter information. Thanks everyone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

弃爱 2024-08-27 03:04:11

我不知道语法问题,通常的访问规则应该适用 - 但这里还有另一个问题,如果这可以工作,因为这些成员函数没有链接。
要完全接受本地类型,setupCallback() 必须是模板函数 - 但不允许没有链接的模板类型参数。

§3.5/8 说:

这些规则未涵盖的名称有
没有联系。此外,除非另有说明,
在本地范围内声明的名称
(3.3.2) 没有链接。

当地班级的成员不包括在内。 §9.3/3 澄清:

本地类的成员函数
(9.8) 没有联系。

长话短说:不要使用本地类的成员函数作为回调,而是使用非本地类。

I don't know about the syntax problem, the usual access rules should apply - but there is another problem here if that would work as these member functions have no linkage.
To accept local types at all, setupCallback() would have to be a template function - but template type arguments with no linkage are not allowed.

§3.5/8 says:

Names not covered by these rules have
no linkage. Moreover, except as noted,
a name declared in a local scope
(3.3.2) has no linkage.

Members of local classes are not covered there. §9.3/3 clarifies that:

Member functions of a local class
(9.8) have no linkage.

Long story cut short: don't use member functions of a local class as callbacks, use a non-local class instead.

度的依靠╰つ 2024-08-27 03:04:11

只要考虑获取地址的具体问题,您的第一个变体就是正确的。获取本地类的成员函数的地址没有任何限制。正确的语法是通常的语法

&NestedClass::someFunction

,仅此而已。您可以尝试将其保存在代码中的中间指针中

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

,我确信您的编译器会接受它。

但是,我怀疑您的代码中存在的问题与获取成员函数地址的正确方法绝对无关。它与声明setupCallback 的第一个参数的方式有关。既然你说它可以使用 &SomeClass::someFunction 作为第一个参数,我希望 setupCallback 被声明为,即

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

它是硬编码的 期望有一个专门指向 SomeClass 成员的指针。您不能提供指向 NestedClass 成员的指针。 NestedClassSomeClass 完全无关,并且指向 NestedClass 成员的指针与指向 SomeClass 成员的指针完全不兼容。这就是它无法编译的原因。

除非有一些东西你没有向我们展示(比如 setupCallback 可能是一个函数模板?或者针对不同的参数类型进行重载?),否则无论你如何采取,你想要做的事情都是不可能实现的成员地址,只要 NestedClassSomeClass 保持无关。函数 setupCallback 设计为仅与 SomeClassSomeClass 一起使用。

提供有关 setupCallback 的更多信息。它是如何声明的?

请注意,如果 setupCallback 被声明为按类类型参数化的函数模板,那么

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

您将无法使用本地类 NestedClass 作为参数的模板参数T。在这种情况下,您的 NestedClass 没有链接这一事实确实发挥了作用。但是,同样,它与获取成员地址无关,而是由没有链接的类不能用作 C++ 中的模板参数这一事实引起的。

You fist variant is the correct one as long as the specific matter of taking the address is considered. There are no restrictions on taking the address of member functions of local classes. The proper syntax is the usual

&NestedClass::someFunction

ans that's it. You can try saving it in an intermediate pointer in your code

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

and I'm sure your compiler will accept it.

However, the problem I suspect exists in your code has absolutely nothing to do with the proper way of taking the address of a member function. It is rather about the way the first parameter of setupCallback is declared. Since you say it works with &SomeClass::someFunction as the first argument, I'd expect setupCallback to be declared as

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

i.e. it is hardcoded to expect a pointer to a member of SomeClass specifically. You cannot supply a pointer to a member of NestedClass instead. NestedClass is completely unrelated to SomeClass and pointers to members of NestedClass are completely incompatible with pointers to members of SomeClass. This is why it won't compile.

Unless there's something you are not showing us (like setupCallback being a function template maybe? Or overloaded for different parameter types?), what you are trying to do is simply impossible to achieve regardless of how you take the member address, as long as NestedClass remains unrelated to SomeClass. Function setupCallback is designed to work with SomeClass and SomeClass only.

Provide more information about setupCallback. How is it declared?

Note that if the setupCallback is declared as a function template parametrized by class type, as in

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

then you won't be able to use the local class NestedClass as template argument for parameter T. In this case the fact that your NestedClass has no linkage does indeed come into play. But, again, it has nothing to do with taking the member address, but rather caused by the fact that classes with no linkage cannot be used as template arguments in C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文