简体   繁体   中英

Could not deduce template argument when testing C++ with google mock

my code uses Google mock to test the class EventLogger .

In first place the compilation fails because the compiler does not find the parameter of the template in a macro, it fails deducting the argument :

candidate: template<class T, class ... Args> auto Filler<traceType>::fill(Args&& ...)
[with T = T; Args = {Args ...}; Class1 traceType = (Class1)1u]
 WRAP_MOCKED_TEMPL_METHOD_1(fill, T);
                            ^
In definition of macro 'WRAP_MOCKED_TEMPL_METHOD_1'
     auto NAME(Args &&...args)\
          ^
Template argument deduction/substitution failed:
     WRAP_MOCKED_TEMPL_METHOD_1(fill, T);

Couldn't deduce template parameter 'T''

So I tried to explicitly add the parameter when calling the function (comment //V2 in the code) but then appears an other error message: filler.fill<Message>(buffer, data, getMessage());

In member function
void EventLogger<traceType>::write(const buffer&, const Message&):
Error: expected primary-expression before '>' token
    `filler.fill<Message>(buffer, data, streamInd);`
                        ^

### Code ### Here is my code.

Class tested

template <Class1 traceType>
class EventLogger
{
public:
    template <typename Message>
    void write(const c1& buffer, const Message& data)
    {
        filler.fill(buffer, data, getMessage());            // V1
        filler.fill<Message>(buffer, data, getMessage());   // V2
    }

private:
    Filler<traceType> filler;
};

The MockClass

template <Class1 traceType>
class MockFiller
{
public:
    MOCK_METHOD3(send, void(c1, const Data::SendReq& msg, Class1::StreamInd&));
    MOCK_METHOD3(receive, void(c1, const Data::ReceiveReq& msg, Class1::StreamInd&));

    template <typename Message>
    void fill(c1 buffer, const Message&, Class1::StreamInd& streamInd)
    {
        ASSERT_TRUE(false);
    }
};

You can find the explanation of the macro MOCK_METHODX in Google documentation .

Specialization of the MockClass

template <>
template <>
void MockFiller<Class1::TYPE_1>::fill<Data::SendReq>(c1 buffer,
            const Data::SendReq& msg, Class1::StreamInd& streamInd)
{
    send(buffer, msg, streamInd);
}

template <>
template <>
void MockFiller<Class1::TYPE_1>::fill<Data::ReceiveReq>(c1 buffer,
            const Data::ReceiveReq& msg, Class1::StreamInd& streamInd)
{
    receive(buffer, msg, streamInd);
}

Constructor of the MockFiller

class MockFillerConstructor
{
public:
    MOCK_METHOD0(construct, std::shared_ptr<MockFiller<Class1::TYPE_1>>());
};

Class called in the class tested with its macro

#define WRAP_MOCKED_TEMPL_METHOD_1(NAME, TEMPL) \
template <typename TEMPL, typename ...Args>\
auto NAME(Args &&...args)\
{\
    return this->mock().NAME<TEMPL>(std::forward<Args>(args)...);\
}

template <Class1 traceType>
class Filler : public CopyableMockBase<MockFiller<traceType>>
{
public:
    WRAP_MOCKED_TEMPL_METHOD_1(fill, T);
};

So my questions are:

  • why the compiler does not automatically find the template parameter
  • why the V2 of my code contains a syntax error

Thanks for your help

I don't know anything about Google Mock, but your V2 is missing a template keyword:

filler.template fill<Message>(buffer, data, getMessage());   // V2

When EventLogger is parsed by the compiler, it does not know what Filler<traceType>::fill is supposed to be, and whether the < that follows is meant to open a list of template arguments or is simply a less-than operator. Without the template keyword, it assumes the latter.

Edit Oh wait a minute. For V1, of course it can't deduce T . Substituting the macro, you define Filler<traceType>::fill like this:

template <typename T, typename... Args>
auto fill(Args &&...args)
{
    return this->mock().fill<T>(std::forward<Args>(args)...);
}

(Also note the missing template in this->mock().fill<T> again here, but that's besides the point really). T is not referenced in the function parameter list. How is the compiler going to deduce what it's supposed to be? Why do you even need that T ? Can't you just do the following?

template <typename... Args>
auto fill(Args &&...args)
{
    return this->mock().fill(std::forward<Args>(args)...);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM