在可变模板中使用声明
using declaration in variadic template
本文关键字:声明 更新时间:2023-10-16
这个问题的灵感来自以下多重继承重载伪歧义的解决方案,这是实现boost::variant的lambda访问者的好方法,正如这个答案所建议的:
我想做如下的事情:
template <typename ReturnType, typename... Lambdas>
struct lambda_visitor : public boost::static_visitor<ReturnType>, public Lambdas... {
using Lambdas...::operator(); //<--- doesn't seem to work
lambda_visitor(Lambdas... lambdas) : boost::static_visitor<ReturnType>() , Lambdas(lambdas)... { }
};
我不确定为打包类型列表添加using子句的正确语法是什么。using
子句对于防止编译器抱怨operator()
是不明确的非常重要,因为它们具有不同的签名。
我找到了一个相当不错的解决方案:
基本上我需要解包一个额外的lambda案例,并将using
子句应用于解包的lambda和其余部分,但在这种情况下,因为我显然不能使用声明的可变列表(至少我不知道语法,如果可能的话),其余部分通过继承'rest'案例来包装,像这样:
template <typename ReturnType, typename... Lambdas>
struct lambda_visitor;
template <typename ReturnType, typename Lambda1, typename... Lambdas>
struct lambda_visitor< ReturnType, Lambda1 , Lambdas...>
: public lambda_visitor<ReturnType, Lambdas...>, public Lambda1 {
using Lambda1::operator();
using lambda_visitor< ReturnType , Lambdas...>::operator();
lambda_visitor(Lambda1 l1, Lambdas... lambdas)
: Lambda1(l1), lambda_visitor< ReturnType , Lambdas...> (lambdas...)
{}
};
template <typename ReturnType, typename Lambda1>
struct lambda_visitor<ReturnType, Lambda1>
: public boost::static_visitor<ReturnType>, public Lambda1 {
using Lambda1::operator();
lambda_visitor(Lambda1 l1)
: boost::static_visitor<ReturnType>(), Lambda1(l1)
{}
};
template <typename ReturnType>
struct lambda_visitor<ReturnType>
: public boost::static_visitor<ReturnType> {
lambda_visitor() : boost::static_visitor<ReturnType>() {}
};
所以我可以通过放置两个using声明来归纳地做到这一点,一个来自未打包的lambda类型,另一个来自父类,父类实际上是同一个类,只是少了一个lambda。
这是一个古老的问题,也是一个很好的答案。在我看来,我们还可以做一件事来改进它。
在c++14及更高版本中,我们不需要指定返回类型——它可以推导出来。
#include <boost/variant.hpp>
#include <type_traits>
namespace detail {
template<typename... Lambdas>
struct lambda_visitor;
template<typename Lambda1, typename... Lambdas>
struct lambda_visitor<Lambda1, Lambdas...>
: public lambda_visitor<Lambdas...>,
public Lambda1
{
using Lambda1::operator ();
using lambda_visitor<Lambdas...>::operator ();
lambda_visitor(Lambda1 l1, Lambdas... lambdas)
: Lambda1(l1)
, lambda_visitor<Lambdas...>(lambdas...) {}
};
template<typename Lambda1>
struct lambda_visitor<Lambda1>
:
public Lambda1
{
using Lambda1::operator ();
lambda_visitor(Lambda1 l1)
: Lambda1(l1) {}
};
}
template<class...Fs>
auto compose(Fs&& ...fs)
{
using visitor_type = detail::lambda_visitor<std::decay_t<Fs>...>;
return visitor_type(std::forward<Fs>(fs)...);
};
用例:boost::variant<int, std::string> x = "foo", y = 4;
auto visitor = compose([](const int& i)
{
std::cout << i << std::endl;
},
[](const std::string& s)
{
std::cout << s << std::endl;
});
boost::apply_visitor(visitor, x);
boost::apply_visitor(visitor, y);
相关文章:
- .cpp和.h文件中的模板专用化声明
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- #ifdef和未声明的标识符
- 没有显式声明的int[]中的foreach
- 在基于范围的for循环中使用结构化绑定声明
- 在将变量声明为引用时,堆在释放后使用
- C++:无法访问声明的受保护成员
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 在函数内部的声明中初始化数组,并在外部使用它
- Visual Studio中的函数声明和函数定义问题
- c++类声明时,相同的例程,不同的成员变量类型
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别