Home > Software design >  invalid use of template-name ‘boost::asio::strand’ without an argument list
invalid use of template-name ‘boost::asio::strand’ without an argument list

Time:11-13

I have an older program that I want to compile on Centos 8 with GCC 8.3.1. The make command looks like this:

CXXFLAGS = -O2 -std=c  11

all: my_prog

my_prog: my_prog.o
    g   my_prog.o -o my_prog -lboost_filesystem -lboost_system -lsecond_level_include -lthird_level_include -lboost_regex -lboost_program_options `mysql_config --libs`

Here is the output for make:

In file included from /usr/local/include/redisclient/redissyncclient.h:16,
                 from /usr/local/include/third_level_include.hpp:11,
                 from /usr/local/include/second_level_include.hpp:40,
                 from my_prog.cpp:9:
/usr/local/include/redisclient/impl/redisclientimpl.h:72:5: error: invalid use of template-name ‘boost::asio::strand’ without an argument list
     boost::asio::strand strand;
     ^~~~~
/usr/local/include/redisclient/impl/redisclientimpl.h:72:5: note: class template argument deduction is only available with -std=c  17 or -std=gnu  17
In file included from /usr/local/include/redisclient/impl/redisclientimpl.h:13,
                 from /usr/local/include/redisclient/redissyncclient.h:16,
                 from /usr/local/include/third_level_include.hpp:11,
                 from /usr/local/include/second_level_include.hpp:40,
from my_prog.cpp:9:
/usr/include/boost/asio/strand.hpp:29:7: note: ‘template<class Executor> class boost::asio::strand’ declared here
 class strand
       ^~~~~~

[snip lots of output]

So I did what it suggested and replaced -std=c 11 with -std=gnu 17 and now I get this:

g   -O2 -std=gnu  17   -c -o my_prog.o my_prog.cpp
In file included from /usr/local/include/redisclient/redissyncclient.h:16,
                 from /usr/local/include/third_level_include.hpp:11,
                 from /usr/local/include/second_level_include.hpp:40,
                 from my_prog.cpp:9:
/usr/local/include/redisclient/impl/redisclientimpl.h:72:5: error: invalid use of template-name ‘boost::asio::strand’ without an argument list
     boost::asio::strand strand;
     ^~~~~
make: *** [<builtin>: my_prog.o] Error 1

Considering that I'm not going to be changing the third party library code from Redis, is there a compiler flag or something I can use to make this error go away? The code compiled once upon a time with GCC 4.4.7 on Centos 6.

EDIT: here is the file that is the source of the error

/*
 * Copyright (C) Alex Nekipelov ([email protected])
 * License: MIT
 */

#ifndef REDISCLIENT_REDISCLIENTIMPL_H
#define REDISCLIENT_REDISCLIENTIMPL_H

#include <boost/array.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <string>
#include <vector>
#include <queue>
#include <map>

#include "../redisparser.h"
#include "../redisbuffer.h"
#include "../config.h"

class RedisClientImpl : public boost::enable_shared_from_this<RedisClientImpl> {
public:
    enum State {
        NotConnected,
        Connected,
        Subscribed,
        Closed
    };  

    REDIS_CLIENT_DECL RedisClientImpl(boost::asio::io_service &ioService);
    REDIS_CLIENT_DECL ~RedisClientImpl();

    REDIS_CLIENT_DECL void handleAsyncConnect(
            const boost::system::error_code &ec,
          const boost::function<void(bool, const std::string &)> &handler);

    REDIS_CLIENT_DECL void close();

    REDIS_CLIENT_DECL State getState() const;

    REDIS_CLIENT_DECL static std::vector<char> makeCommand(const std::vector<RedisBuffer> &items);

    REDIS_CLIENT_DECL RedisValue doSyncCommand(const std::vector<RedisBuffer> &buff);

    REDIS_CLIENT_DECL void doAsyncCommand(
            const std::vector<char> &buff,
            const boost::function<void(const RedisValue &)> &handler);

    REDIS_CLIENT_DECL void sendNextCommand();
    REDIS_CLIENT_DECL void processMessage();
    REDIS_CLIENT_DECL void doProcessMessage(const RedisValue &v);
    REDIS_CLIENT_DECL void asyncWrite(const boost::system::error_code &ec, const size_t);
    REDIS_CLIENT_DECL void asyncRead(const boost::system::error_code &ec, const size_t);

    REDIS_CLIENT_DECL void onRedisError(const RedisValue &);
    REDIS_CLIENT_DECL static void defaulErrorHandler(const std::string &s);

    REDIS_CLIENT_DECL static void append(std::vector<char> &vec, const RedisBuffer &buf);
    REDIS_CLIENT_DECL static void append(std::vector<char> &vec, const std::string &s);
    REDIS_CLIENT_DECL static void append(std::vector<char> &vec, const char *s);
    REDIS_CLIENT_DECL static void append(std::vector<char> &vec, char c);
    template<size_t size>
    static inline void append(std::vector<char> &vec, const char (&s)[size]);

    template<typename Handler>
    inline void post(const Handler &handler);

    boost::asio::strand strand; // Here it is!
    boost::asio::ip::tcp::socket socket;
    RedisParser redisParser;
    boost::array<char, 4096> buf;
    size_t subscribeSeq;
    typedef std::pair<size_t, boost::function<void(const std::vector<char> &buf)> > MsgHandlerType;
    typedef boost::function<void(const std::vector<char> &buf)> SingleShotHandlerType;

    typedef std::multimap<std::string, MsgHandlerType> MsgHandlersMap;
    typedef std::multimap<std::string, SingleShotHandlerType> SingleShotHandlersMap;

    std::queue<boost::function<void(const RedisValue &v)> > handlers;
    MsgHandlersMap msgHandlers;
    SingleShotHandlersMap singleShotMsgHandlers;

    struct QueueItem {
        boost::function<void(const RedisValue &)> handler;
        boost::shared_ptr<std::vector<char> > buff;
    };

    std::queue<QueueItem> queue;

    boost::function<void(const std::string &)> errorHandler;
    State state;
};

template<size_t size>
void RedisClientImpl::append(std::vector<char> &vec, const char (&s)[size])
{
    vec.insert(vec.end(), s, s   size);
}

template<typename Handler>
inline void RedisClientImpl::post(const Handler &handler)
{
    strand.post(handler);
}


#ifdef REDIS_CLIENT_HEADER_ONLY
#include "redisclientimpl.cpp"
#endif

#endif // REDISCLIENT_REDISCLIENTIMPL_H

CodePudding user response:

UPDATE

You're using an old version of that library. Use v0.6.1 or higher: https://github.com/nekipelov/redisclient/pull/53


All executor interfaces have been upgraded a (long) while ago.

Strands used to be nested typedefs (and there is still one for "legacy" compatibility in io_service if that is enabled).

However, the new type succeeding is is boost::asio::strand<Executor> (so e.g. boost::asio::io_context::executor_type). You can easily make a strand for any executor, e.g.:

 auto s = make_strand(io_object.get_executor()); 

What you are seeing is apparent mix-up of these names. I suspect it may have to do with

  • local typedefs that alias strand
  • local variables named strand (though I don't see immediately how that would lead to the exact message mposted)
  • most likely: you have a using namespace that pulls in the new strand template

With this information, you should be able to sort it out.

Of course, had you posted the code, we could have shown it for you.

  • Related