4

I want to send std::array as a parameter to my virtual function

class Handler:
    {
    public:
        template <std::size_t N>
        virtual void handle(const std::array<char, N>& msg, std::vector<boost::asio::const_buffer>& buffers) = 0;
    };

but gcc said templates may not be 'virtual'. So how i pass a std::array to my function?

CharliePrynn
  • 3,034
  • 5
  • 40
  • 68
Mike Minaev
  • 1,912
  • 4
  • 23
  • 33

3 Answers3

5

A member function template may not be virtual. See this question.

However, you can make a virtual member function takes a std::array of specific size by moving the N out to the Handler:

template <size_t N>
class Handler:
{
public:
    virtual void handle(const std::array<char, N>& msg,
        std::vector<boost::asio::const_buffer>& buffers) = 0;
};

Or simply passing a vector<char>, which given the context, could make more sense:

class Handler:
{
public:
    virtual void handle(const std::vector<char>& msg,
        std::vector<boost::asio::const_buffer>& buffers) = 0;
};
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
2

One possible solution is to make a member function template that accepts std::array and forwards it to your virtual member function in such a way that the size of the array is passed as a normal function argument rather than a non-type template argument. An illustration:

virtual void handle(const char* arr, std::size_t sz, std::vector<boost::asio::const_buffer>& buffers) = 0;

template <std::size_t sz>
void handle(const std::array<char, sz>& arr, std::vector<boost::asio::const_buffer>& buffers) {
  handle(sz ? &arr[0] : nullptr, sz, buffers);
}
Lingxi
  • 14,579
  • 2
  • 37
  • 93
0

(simplistic) explanation:

  1. A virtual function works because each class maintains a table of addresses of the virtual functions for that class.

  2. A template function (or method) is not code, it's instructions on how to generate code.

so this:

template <std::size_t N>
void handle(const std::array<char, N>& msg, std::vector<boost::asio::const_buffer>& buffers)
{
   // stuff that looks like code
}

does not define a method. It tells the compiler how to write a different method (function) for each and any value of N.

in which case:

template <>
void handle(const std::array<char, 10>& msg, std::vector<boost::asio::const_buffer>& buffers)

and

template <>
void handle(const std::array<char, 20>& msg, std::vector<boost::asio::const_buffer>& buffers)

are actually different functions (that happen to behave similarly). Because they are different functions, they will occupy different addresses.

Therefore in order for them to be virtual, there must be 2 entries in the virtual function table.

This, for example, would work:

class Handler:
    {
    public:
        virtual void handle(const std::array<char, 10>& msg, std::vector<boost::asio::const_buffer>& buffers) = 0;

        virtual void handle(const std::array<char, 20>& msg, std::vector<boost::asio::const_buffer>& buffers) = 0;

        // and so on for every value on N you need.
    };
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142