【问题标题】:how to define a member function of template class which return a nested class object如何定义返回嵌套类对象的模板类的成员函数
【发布时间】:2019-04-20 18:43:21
【问题描述】:
template<typename IPC_TYPE>
class Poller
{
private:

public:
    struct Event
    {
        std::shared_ptr<IPC> ipc;
        enum Status
        {
            NONE = 0, POLLIN = 1, POLLHUP = 2, MessageArrival = 3
        }status;
    };

    //block wait
    Event wait(size_t max_wait_time = 50);
};

 template<typename IPC_TYPE>
    Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait(size_t max_wait_time = 50)
    {
        Event e;
        return Event();
    }

我定义了一个类模板Poller 和一个嵌套类Event,我正在编写一个Poller 的成员函数,它返回一个Event 对象,但是编译器报告" 错误 C2061 语法错误:标识符“事件”IPC poller.cpp 8 ",我该怎么办?谢谢!

【问题讨论】:

  • 你试过Poller&lt;IPC_TYPE&gt;::Event吗?
  • 是的,也失败了
  • 通常问题在于循环依赖。确保你的头文件不相互包含
  • typename Poller&lt;IPC_TYPE&gt;::Event 怎么样?
  • 在你的类结构中,它应该是std::shared_ptr&lt;IPC&gt; ipc; 还是应该是std::shared_ptr&lt;IPC_TYPE&gt; ipc;

标签: c++ c++11 templates visual-c++ inner-classes


【解决方案1】:

编译器不知道Poller&lt;IPC_TYPE&gt;::EventPoller&lt;IPC_TYPE&gt;的成员变量还是嵌套类型。

因此我们必须输入typename 来消除这种歧义,如下所示:

DEMO is here.

template<typename IPC_TYPE>
typename Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait(size_t max_wait_time)
{
    Event e;
    return Event();
}

【讨论】:

    【解决方案2】:

    查看您当前的代码:

    template<typename IPC_TYPE>
    class Poller {    
    public:
        struct Event {
            std::shared_ptr<IPC> ipc;
            enum Status
            {
                NONE = 0, POLLIN = 1, POLLHUP = 2, MessageArrival = 3
            } status;
        };
    
        //block wait
        Event wait(size_t max_wait_time = 50);
    };
    
    template<typename IPC_TYPE>
    Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait(size_t max_wait_time = 50) {
        Event e;
        return Event();
    }
    

    我注意到几个问题:

    • 1) std::shared_ptr&lt;IPC&gt; ipc; 我相信应该是std::shared_ptr&lt;IPC_TYPE&gt; ipc;
    • 2) 已经被user:Hiroki 回答——typename 需要在Poller&lt;IPC_TYPE&gt;::Event 之前使用来声明类型名,以便编译器知道如何识别您的预期用途。请参阅他的回答,以获得更详细的描述和更完整的说明,了解您为什么需要 typename
    • 3) 由于您在超类的主体之外声明函数,MSVS 2017 CE 给出了有关具有默认值的编译器错误。 (见下文)。
    • 4) 不确定您是否正在创建一个临时... 然后通过其构造函数创建并返回一个实例,或者template argument 是否将是您正在调用的某种functorfunction pointer
    • 5) 您在Event 中有一个std::shared_ptr&lt;IPC_TYPE&gt; 成员,但没有看到为类型IPC_TYPE 创建任何动态内存。所以我添加了一个用户定义的默认构造函数来设置这个,以便查看对象的构造函数、析构函数、运算符、成员函数等被正确调用、创建和销毁。

    (3) - 编译器错误:

    1>------ Build started: Project: StackQA, Configuration: Debug Win32 ------
    1>main.cpp
    1>c:\users\...\main.cpp(41): error C5037: 'Poller<IPC_TYPE>::wait': an out-of-line definition of a member of a class template cannot have default arguments
    1>Done building project "StackQA.vcxproj" -- FAILED.
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
    

    有两种方法可以修复上述编译器错误:

    • A) 删除超类之外的定义中的默认值。
    • B) 在内部类中编写函数体。如果您决定选择这种编写函数体的方法;它实际上会首先消除您问题的全部需求和目的,因为您将在内部类中定义它。

    这是你上面的类的一个工作示例:

    #include <iostream>
    #include <exception>
    #include <memory>
    
    // Classes A & B are just basic classes with ctor & dtor displaying a message
    class A {
    public:
        A() { std::cout << "A CTOR called\n"; }
        ~A() { std::cout << "A DTOR called\n"; }
    };
    
    class B {
    public:
        B() { std::cout << "B CTOR called\n"; }
        ~B() { std::cout << "B DTOR called\n"; }
    };
    
    // Classes C & D are functors where their operator invokes a message to be displayed
    class C {
    public:
        void operator()() { std::cout << "Functor C called\n"; }
    };
    
    class D {
    public:
        void operator()() { std::cout << "Functor D called\n"; }
    };
    
    template <typename IPC_TYPE>
    class Poller {
    public:
        struct Event {
            std::shared_ptr<IPC_TYPE> ipc; // Made correction here from IPC to IPC_TYPE
            enum Status {
                NONE = 0,
                POLLIN = 1,
                POLLHUP = 2,
                MESSAGE_ARRIVAL = 3, // Changed to All Caps... (personal preference)
            } status;
    
                // Added this constructor to actually make a shared_ptr of IPC_TYPE
            Event() {
                ipc = std::make_shared<IPC_TYPE>();
            }    
        };
    
        // Defined the function body within the inner class which also prevents your compiler error.
        Event wait( size_t max_wait_time = 50 ) {
            // Not sure of your intentions here, but for demonstration purposes
            // I've just commented out the temporary and just returned the ctor
            // Event e;
            return Event();
        }
    };
    
    // To define it outside of class remove the body from the inner class above,
    // uncomment this section, and don't forget to use `typename`.
    // Also make sure that your parameter does not have a default value here.
    /*template<typename IPC_TYPE>
    typename Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait( size_t wait_time ) {
        // Not sure of your intentions here, but for demonstration purposes
        // I've just commented out the temporary and just returned the ctor
        //Event e;
        return Event();
    }
    */    
    
    int main() {
        try {
            Poller<A> p1;
            p1.wait( 10 );
    
            Poller<B> p2;
            p2.wait( 12 );
    
            Poller<C> p3;       
            Poller<C>::Event e1 = p3.wait( 7 );
            e1.ipc->operator()();
    
            Poller<D> p4;
            Poller<D>::Event e2 = p4.wait( 9 );
            e2.ipc->operator()();
    
        } catch( std::runtime_error& e ) {
            std::cerr << e.what() << std::endl;
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    

    -输出-

    A CTOR called
    A DTOR called
    B CTOR called
    B DTOR called
    Functor C called
    Functor D called
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多