在没有参数列表的情况下无效使用模板名称“boost::asio::strand”
invalid use of template-name ‘boost::asio::strand’ without an argument list
我有一个旧程序想在 Centos 8 上用 GCC 8.3.1 编译。 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=c++11
替换为 -std=gnu++17
现在
我明白了:
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
UPDATE
You're using an old version of that library. Use v0.6.1 or higher:
https://github.com/nekipelov/redisclient/pull/53
所有执行器接口已upgraded a (long) while ago。
Strands 曾经是嵌套的 typedef(如果启用的话,io_service
中仍然有一个用于“遗留”兼容性的)。
然而,新的继承类型是 boost::asio::strand<Executor>
(例如 boost::asio::io_context::executor_type
)。您可以轻松地为任何执行者创建一个 strand,例如:
auto s = make_strand(io_object.get_executor());
您看到的是这些名称的明显混淆。我怀疑这可能与
有关
- 别名为
strand
的本地类型定义
- 名为
strand
的局部变量(虽然我没有立即看到这将如何导致发布的确切消息)
- 最有可能:您有一个
using namespace
可以引入新的 strand
模板
有了这些信息,你应该就能搞定了。
当然,如果您发布了代码,我们可以为您展示它。
我有一个旧程序想在 Centos 8 上用 GCC 8.3.1 编译。 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=c++11
替换为 -std=gnu++17
现在
我明白了:
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
UPDATE
You're using an old version of that library. Use v0.6.1 or higher: https://github.com/nekipelov/redisclient/pull/53
所有执行器接口已upgraded a (long) while ago。
Strands 曾经是嵌套的 typedef(如果启用的话,io_service
中仍然有一个用于“遗留”兼容性的)。
然而,新的继承类型是 boost::asio::strand<Executor>
(例如 boost::asio::io_context::executor_type
)。您可以轻松地为任何执行者创建一个 strand,例如:
auto s = make_strand(io_object.get_executor());
您看到的是这些名称的明显混淆。我怀疑这可能与
有关- 别名为
strand
的本地类型定义
- 名为
strand
的局部变量(虽然我没有立即看到这将如何导致发布的确切消息) - 最有可能:您有一个
using namespace
可以引入新的strand
模板
有了这些信息,你应该就能搞定了。
当然,如果您发布了代码,我们可以为您展示它。