【问题标题】:invalid use of template-name ‘boost::asio::strand’ without an argument list在没有参数列表的情况下无效使用模板名称“boost::asio::strand”
【发布时间】:2021-12-23 08:58:20
【问题描述】:

我有一个旧程序,我想用 GCC 8.3.1 在 Centos 8 上编译。 make 命令如下所示:

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`

这是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
       ^~~~~~

[截取大量输出]

所以我按照它的建议做了,用-std=gnu++17 替换了-std=c++11,现在 我明白了:

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

考虑到我不会从 Redis 更改第三方库代码,是否有编译器标志或可以用来消除此错误的东西?曾在 Centos 6 上使用 GCC 4.4.7 编译的代码。

编辑:这是错误来源的文件

/*
 * Copyright (C) Alex Nekipelov (alex@nekipelov.net)
 * 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

【问题讨论】:

  • 您是否...包括除代码之外的所有内容?这将很难解决。
  • 是的,这可能会有所帮助。添加代码。

标签: c++ c++11 boost boost-asio


【解决方案1】:

更新

您正在使用该库的旧版本。使用 v0.6.1 或更高版本: https://github.com/nekipelov/redisclient/pull/53


所有执行器接口都已经upgraded a (long) while ago

Strands 曾经是嵌套的 typedef(如果启用的话,io_service 中仍有一个用于“遗留”兼容性)。

但是,后续的新类型是boost::asio::strand&lt;Executor&gt;(例如boost::asio::io_context::executor_type)。您可以轻松地为任何执行者创建一个链,例如:

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

您所看到的是这些名称的明显混淆。我怀疑这可能与

  • 别名为strand 的本地类型定义
  • 名为 strand 的局部变量(虽然我没有立即看到这将如何导致发布的确切消息)
  • 最有可能:您有一个using namespace,它引入了新的strand 模板

有了这些信息,你应该可以整理出来了。

当然,如果您发布了代码,我们可以为您展示。

【讨论】:

  • 这是一个合理的要求,我已经添加了代码,我在第 72 行根据编译器错误进行了注释。
  • 我没有意识到它是一个外部库。你当然可以链接到那个(假设github.com/nekipelov/redisclient
  • 我无法复制。您使用什么版本的库(git commit)?你用的是哪个版本的 Boost?请显示一个无法编译的最小示例程序。我预计会包含一些 + int main() {},因为您之前认为没有必要包含代码。
  • 使用 Boost 1.77 并从最新的 master (fbf052ef8e3772d17) 合并 redisclient.h,这在 c++11 中编译得很好:pastebin.ubuntu.com/p/PQC6cy3P9k 所以,我仍然怀疑选择错误的宏或 using-directives。
  • 看起来您的错误已在几年前得到修复:github.com/nekipelov/redisclient/pull/53(修复于 2018 年 2 月发布)。 v0.6.1 包含该修复(也是 2018 年 2 月)。事实上,回到 v0.6.0 会重现您的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 2012-05-03
  • 1970-01-01
相关资源
最近更新 更多