使用 Boost 预处理器将 Any 提升到 Boost Variant
Boost Any to Boost Variant using Boost Preprocessor
在我的项目中,我用尽了 boost::any
和 boost::variant
。为此,我在上一个问题 中设计了一个从 boost::any
到 boost::variant
的通用转换例程。非常感谢帮助我的人。
找到的解决方案对我来说没有任何问题,但有一些严重的缺点。完全模板化解决方案产生的代码膨胀可能令人望而却步,有时对于简单转换来说是不必要的。 (我没有提到编译时间。)
现在我有了让模板专门化用于简单(非通用)转换的想法,但我发现必要的代码很繁琐且容易出错。特别是,如果一个人必须一遍又一遍地完成这项任务。
下面的代码片段说明了这个问题。想象一下,在一个典型的应用程序中,一个人可能有 20 种或更多类型!
#include <boost/preprocessor.hpp>
#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <boost/optional.hpp>
#include <iostream>
template<typename VARIANT>
boost::optional<VARIANT> anyToVariant(const boost::any& any) {
boost::optional<VARIANT> ret;
// General implementation omitted.
// The implementation is lengthy and produces an enormous code bloat. In some cases it is the best solution.
return ret;
}
// Specialized Template reduces code bloat. But is error-prone to type write for every new variant type.
template<>
boost::optional <boost::variant<int, double, std::string>> anyToVariant(const boost::any& any) {
boost::optional<boost::variant<int, double, std::string>> ret;
if (any.type() == typeid(int)) {
ret = boost::any_cast<int>(any);
}
if (any.type() == typeid(double)) {
ret = boost::any_cast<double>(any);
}
if (any.type() == typeid(std::string)) {
ret = boost::any_cast<std::string>(any);
}
return ret;
}
// Should be implemented with boost preprocessor
#define BOOST_ANY_TO_VARIANT(TypeList)
// Better would be a macro like this
BOOST_ANY_TO_VARIANT(int, double, std::string); // Create the above template specialization
int main() {
boost::variant<int, double, std::string> v;
boost::any x = 4;
v=*anyToVariant<boost::variant<int, double, std::string>>(x);
}
更好的解决方案当然是宏,但不幸的是我无法用 boost-preprocessor
实现这个宏。虽然技术还不够,但我相信可以做到。
有boost-preprocessor
经验的人可以帮我解决我的问题吗?
我能想到的最佳解决方案是像下面这样的宏:
#define BOOST_ANY_TO_VARIANT(VariantType) \
// Magic?
typedef boost::variant<int, std::string, double> MyVariant;
BOOST_ANY_TO_VARIANT(MyVariant)
但我怀疑这个解决方案是否可行。
给你:
#define ANY_TO_VARIANT_OP_VARIANT(typeSeq) \
boost::optional<boost::variant<BOOST_PP_SEQ_ENUM(typeSeq)>>
#define ANY_TO_VARIANT_CONVERT_AND_RETURN(r, data, elem) \
if (any.type() == typeid(elem)) { \
return Ret{boost::any_cast<elem>(any)}; \
}
#define SPECIALIZE_BOOST_ANY_TO_VARIANT(typeSeq) \
template<> \
ANY_TO_VARIANT_OPT_VARIANT(typeSeq) anyToVariant(const boost::any& any) { \
using Ret = ANY_TO_VARIANT_OPT_VARIANT(typeSeq); \
BOOST_PP_SEQ_FOR_EACH(ANY_TO_VARIANT_CONVERT_AND_RETURN, ~, typeSeq) \
return Ret{}; \
}
用法:
SPECIALIZE_BOOST_ANY_TO_VARIANT((int)(double)(std::string))
在我的项目中,我用尽了 boost::any
和 boost::variant
。为此,我在上一个问题 boost::any
到 boost::variant
的通用转换例程。非常感谢帮助我的人。
找到的解决方案对我来说没有任何问题,但有一些严重的缺点。完全模板化解决方案产生的代码膨胀可能令人望而却步,有时对于简单转换来说是不必要的。 (我没有提到编译时间。)
现在我有了让模板专门化用于简单(非通用)转换的想法,但我发现必要的代码很繁琐且容易出错。特别是,如果一个人必须一遍又一遍地完成这项任务。
下面的代码片段说明了这个问题。想象一下,在一个典型的应用程序中,一个人可能有 20 种或更多类型!
#include <boost/preprocessor.hpp>
#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <boost/optional.hpp>
#include <iostream>
template<typename VARIANT>
boost::optional<VARIANT> anyToVariant(const boost::any& any) {
boost::optional<VARIANT> ret;
// General implementation omitted.
// The implementation is lengthy and produces an enormous code bloat. In some cases it is the best solution.
return ret;
}
// Specialized Template reduces code bloat. But is error-prone to type write for every new variant type.
template<>
boost::optional <boost::variant<int, double, std::string>> anyToVariant(const boost::any& any) {
boost::optional<boost::variant<int, double, std::string>> ret;
if (any.type() == typeid(int)) {
ret = boost::any_cast<int>(any);
}
if (any.type() == typeid(double)) {
ret = boost::any_cast<double>(any);
}
if (any.type() == typeid(std::string)) {
ret = boost::any_cast<std::string>(any);
}
return ret;
}
// Should be implemented with boost preprocessor
#define BOOST_ANY_TO_VARIANT(TypeList)
// Better would be a macro like this
BOOST_ANY_TO_VARIANT(int, double, std::string); // Create the above template specialization
int main() {
boost::variant<int, double, std::string> v;
boost::any x = 4;
v=*anyToVariant<boost::variant<int, double, std::string>>(x);
}
更好的解决方案当然是宏,但不幸的是我无法用 boost-preprocessor
实现这个宏。虽然技术还不够,但我相信可以做到。
有boost-preprocessor
经验的人可以帮我解决我的问题吗?
我能想到的最佳解决方案是像下面这样的宏:
#define BOOST_ANY_TO_VARIANT(VariantType) \
// Magic?
typedef boost::variant<int, std::string, double> MyVariant;
BOOST_ANY_TO_VARIANT(MyVariant)
但我怀疑这个解决方案是否可行。
给你:
#define ANY_TO_VARIANT_OP_VARIANT(typeSeq) \
boost::optional<boost::variant<BOOST_PP_SEQ_ENUM(typeSeq)>>
#define ANY_TO_VARIANT_CONVERT_AND_RETURN(r, data, elem) \
if (any.type() == typeid(elem)) { \
return Ret{boost::any_cast<elem>(any)}; \
}
#define SPECIALIZE_BOOST_ANY_TO_VARIANT(typeSeq) \
template<> \
ANY_TO_VARIANT_OPT_VARIANT(typeSeq) anyToVariant(const boost::any& any) { \
using Ret = ANY_TO_VARIANT_OPT_VARIANT(typeSeq); \
BOOST_PP_SEQ_FOR_EACH(ANY_TO_VARIANT_CONVERT_AND_RETURN, ~, typeSeq) \
return Ret{}; \
}
用法:
SPECIALIZE_BOOST_ANY_TO_VARIANT((int)(double)(std::string))