как определить функцию-член класса шаблона, которая возвращает вложенный объект класса - PullRequest
0 голосов
/ 18 ноября 2018
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 ", как мне быть? Спасибо!

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

Глядя на ваш текущий код:

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; Iверить должно быть std::shared_ptr<IPC_TYPE> ipc;
  • 2) На вопрос user:Hiroki уже нужно ответить *1014* - необходимо typename использовать перед Poller<IPC_TYPE>::Event, чтобы объявить имя типа, чтобы компилятор знал, как распознать ваше предполагаемое использование.Обратитесь к его ответу для более подробного описания и более полного объяснения того, почему вам нужно typename.
  • 3) Поскольку вы объявляете функцию вне тела суперкласса, MSVS 2017 CE выдает ошибку компилятора оимеющий значение по умолчанию.(См. Ниже).
  • 4) Не уверен, что вы создаете временный ... Затем создаете и возвращаете экземпляр его конструктором или если template argument будет чем-то вроде functor или function pointer что вы вызываете.
  • 5) У вас есть std::shared_ptr<IPC_TYPE> член в Event, но вы не видите динамической памяти, создаваемой для типа 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 ==========

Существует 2 способа исправления вышеуказанной ошибки компилятора:

  • 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
0 голосов
/ 18 ноября 2018

Компилятор не знает, является ли 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();
}
...