如何定义模板 class 的成员函数,其中 return 嵌套 class 对象
how to define a member function of template class which return a nested class object
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();
}
我定义了一个 class 模板 Poller
和一个嵌套的 class Event
,我正在编写 Poller
的成员函数 return 一个 Event
对象,但编译器报告 "
Error C2061 语法错误:标识符'Event' IPC poller.cpp 8
",我该怎么办?谢谢!
编译器不知道Poller<IPC_TYPE>::Event
是Poller<IPC_TYPE>
的成员变量还是嵌套类型
因此我们必须键入 typename
来消除这种歧义,如下所示:
template<typename IPC_TYPE>
typename Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait(size_t max_wait_time)
{
Event e;
return Event();
}
查看您当前的代码:
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<IPC> ipc;
我认为应该是 std::shared_ptr<IPC_TYPE> ipc;
- 2) 已被
user:Hiroki
回答——需要在 Poller<IPC_TYPE>::Event
之前使用 typename
来声明类型名,以便编译器知道如何识别您的预期用途。请参阅他的回答以获得更详细的描述和更完整的解释为什么你需要 typename
.
- 3) 由于您是在超级 class 的主体之外声明函数,因此
MSVS 2017 CE
会给出有关具有默认值的编译器错误。 (见下文)。
- 4) 不确定您是否正在创建一个临时...然后通过其构造函数创建和 return 一个实例,或者
template argument
是否是某种 functor
或function pointer
您正在调用。
- 5) 您在
Event
中有一个 std::shared_ptr<IPC_TYPE>
成员,但没有看到为类型 IPC_TYPE
创建的任何动态内存。所以我添加了一个用户定义的默认构造函数,它设置了 this 以便看到对象的构造函数、析构函数、运算符、成员函数等被正确调用、创建和销毁。
(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) 删除定义中超出超级 class.
的默认值
- B) 在内部 class 中写入函数体。如果您决定选择这种编写函数体的方法;它实际上首先会消除您问题的全部需求和目的,因为您将在内部 class.
中定义它
这是上面 class 的一个工作示例:
#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;
}
-Output-
A CTOR called
A DTOR called
B CTOR called
B DTOR called
Functor C called
Functor D called
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();
}
我定义了一个 class 模板 Poller
和一个嵌套的 class Event
,我正在编写 Poller
的成员函数 return 一个 Event
对象,但编译器报告 "
Error C2061 语法错误:标识符'Event' IPC poller.cpp 8
",我该怎么办?谢谢!
编译器不知道Poller<IPC_TYPE>::Event
是Poller<IPC_TYPE>
的成员变量还是嵌套类型
因此我们必须键入 typename
来消除这种歧义,如下所示:
template<typename IPC_TYPE>
typename Poller<IPC_TYPE>::Event Poller<IPC_TYPE>::wait(size_t max_wait_time)
{
Event e;
return Event();
}
查看您当前的代码:
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<IPC> ipc;
我认为应该是std::shared_ptr<IPC_TYPE> ipc;
- 2) 已被
user:Hiroki
回答——需要在Poller<IPC_TYPE>::Event
之前使用typename
来声明类型名,以便编译器知道如何识别您的预期用途。请参阅他的回答以获得更详细的描述和更完整的解释为什么你需要typename
. - 3) 由于您是在超级 class 的主体之外声明函数,因此
MSVS 2017 CE
会给出有关具有默认值的编译器错误。 (见下文)。 - 4) 不确定您是否正在创建一个临时...然后通过其构造函数创建和 return 一个实例,或者
template argument
是否是某种functor
或function pointer
您正在调用。 - 5) 您在
Event
中有一个std::shared_ptr<IPC_TYPE>
成员,但没有看到为类型IPC_TYPE
创建的任何动态内存。所以我添加了一个用户定义的默认构造函数,它设置了 this 以便看到对象的构造函数、析构函数、运算符、成员函数等被正确调用、创建和销毁。
(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) 删除定义中超出超级 class. 的默认值
- B) 在内部 class 中写入函数体。如果您决定选择这种编写函数体的方法;它实际上首先会消除您问题的全部需求和目的,因为您将在内部 class. 中定义它
这是上面 class 的一个工作示例:
#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;
}
-Output-
A CTOR called A DTOR called B CTOR called B DTOR called Functor C called Functor D called