I have an member function, which receives some data from serial port and few parser functions in the same class, which then parse recieved data to specific format. All the parse functions take same parameter. What I want is to pass any kind of parser function to recieve function an to make recieve function return same type as parser returns. Wha I have tried:
class Foo
{
public:
template<typename F>
auto receive(F parser) -> decltype(parser(std::declval(QByteArray)))
{
QByteArray response = readAll();
return parser(response);
}
QHash<QString, QVariant> parseHash(QByteArray data);
QString parseString(QByteArray data);
void doStuff();
};
void Foo::doStuff()
{
QHash<QString, QVariant> response = receive(&Foo::parseHash); // Compilation error
// Another try..
response = receive(std::bind(&Foo::parseHash, this, std::placeholders::_1)); // Also compilation error
}
In both cases compilation fails with message
error: C2893: Failed to specialize function template 'unknown-type Foo::receive(F)'
With the following template arguments: 'F=QHash (__thiscall Foo::LocalConnector::* )(QByteArray)'
In the below snippet:
QHash<QString, QVariant> response = receive(&Foo::parseHash);
parseHash
is a non-static member function, hence it requires an implicit object parameter. Otherwise, the expression SFINAE fails, making receive
a non-viable candidate.
The following should work instead:
void Foo::doStuff()
{
auto callback = std::bind(&Foo::parseHash, this, std::placeholders::_1);
QHash<QString, QVariant> response = receive(callback);
}
Or simply make parseHash
a static member function.
Also, there's a typo in your expression SFINAE, it should be:
decltype(parser(std::declval<QByteArray>()))