【问题标题】:Boost.Variant, Boost.MPL: How to append types?Boost.Variant、Boost.MPL:如何附加类型?
【发布时间】:2012-01-08 12:05:09
【问题描述】:

我看着这个grate code based on boost.Any,不禁想知道我们是否可以改用Boost.Variant。我想知道这样的 API 是否可行:

void voidFunc()
{
    std::cout << "void called" << std::endl;
}

int stringFunc(std::string str)
{
    std::cout << str << std::endl;
    return 0;
}

int main()
{
    some_map_like_type<std::string, boost::variant> funcs;
    funcs.insert<void , void >("voidFunc", &voidFunc)); // now our variant vould contain something like boost::function<void, void>
    funcs.insert<int , std::string>("stringFunc", &stringFunc)); // and now we added to our variant a new type: boost::function<int , std::string>
    funcs.insert<void , void >("voidFunc2", &voidFunc)); // and now our variant should not change because it already contains boost::function<void, void> type


    // And here when all the fun part is:
    funcs["voidFunc"](); // compiles
    funcs["stringFunc"]("hello"); // compiles
    funcs["stringFunc"](some_not_std_string_class); // does not compile.
    return 0;
}

这意味着最后编译器必须编译类似:

void voidFunc()
{
    std::cout << "void called" << std::endl;
}

int stringFunc(std::string str)
{
    std::cout << str << std::endl;
    return 0;
}

int main()
{
    some_map_like_type<std::string, boost::variant< boost::function<void , void>, boost::function<int , std::string> > > funcs;
    funcs.insert<void , void >("voidFunc", &voidFunc)); // now our variant vould contain something like boost::function<void, void>
    funcs.insert<int , std::string>("stringFunc", &stringFunc)); // and now we added to our variant a new type: boost::function<int , std::string>
    funcs.insert<void , void >("voidFunc2", &voidFunc)); // and now our variant should not change because it already contains boost::function<void, void> type


    // And here when all the fun part is:
    funcs["voidFunc"](); // compiles
    funcs["stringFunc"]("hello"); // compiles
    funcs["stringFunc"](some_not_std_string_class); // here it would give error and would not compile
    return 0;
}

更新:

我尝试了什么(基于Variant docsMPL demosdocs):

#include <boost/static_assert.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/multiplies.hpp>
#include <boost/mpl/placeholders.hpp>

#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include <vector>

class sudo_science
{
public:
    typedef  boost::mpl::vector_c<int> types_vector1;

    typedef boost::make_recursive_variant< types_vector1 >::type recursive_variant_t;

    std::vector< recursive_variant_t > variant_seq;

    template <typename T>
    void append(T val)
    {
        typedef  boost::mpl::push_back<types_vector1,T>::type types_vector1;
        variant_seq.push_back(val);
        return;
    }

    std::vector< recursive_variant_t > give_me_end_variant()
     {
         return variant_seq;
     }
};

int main()
{
    sudo_science a;
    a.append<float>(1.0);
    a.append<std::string>("Stack and Boost");

    //sorry for C++11
    auto varint = a.give_me_end_variant();

    return 0;
}

但编译失败,出现 2 个相同的错误:

Error   1   error C2665: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : none of the 2 overloads could convert all the argument types    c:\program files\boost\include\boost\variant\variant.hpp    1330    1

【问题讨论】:

  • 你想完成什么?可能有更简单的方法。
  • 唯一的困难是只有返回类型不同的函数。通过重载,我可以轻松解决 funcs["stringFunc"]("hello"); 甚至发现 funcs["stringFunc"](some_not_std_string_class); 不应该编译。但是在变体中添加function&lt;int, std::string&gt;,它就会分崩离析。
  • @MSalters:描述的问题(如果你遇到同样的问题,请告诉我?)here
  • @GMan:描述的问题/我试图完成的工作here

标签: c++ boost types boost-mpl boost-variant


【解决方案1】:

这是不可能的。 operator[] 是运行时的东西,而类型是编译时的东西。那么编译器应该编译以下内容吗?

char const* str;
if (some_condition())
  str = "voidFunc";
else
  str = "stringFunc";
// ... some more code
if (some_condition())
  funcs[str]();
else
  funcs[str](str);

编译器应该如何知道对some_condition() 的第二次调用是否给出与以前相同的结果?或者中间的代码是否修改了str的值?

下面的呢:

void call(some_map_like_type<std::string, boost::variant> const& funcs)
{
  funcs["voidFunc"]();
}

编译器应该如何知道在调用时funcs 是否包含一个条目映射"voidFunc" 到一个没有参数的函数?如果它被调用一次的值会发生,而一次调用的值不会呢?

根据您实际想要实现的目标,可能有一种方法可以通过模板和constexpr 函数来实现。但是请注意,运行时发生的任何事情都不会影响代码是否编译,原因很简单,代码在编译之前无法运行。

【讨论】:

  • updated q...我希望这可以通过this之类的方式来完成
  • 错误答案,有可能:参数类型是已知的。
  • @MSalters:不,编译时接受的参数类型是已知的。它们由对funcs.insert&lt;&gt; 的调用指定,并取决于对该函数的哪些调用。
  • boost::variant 包含有限数量的类型; funcs.insert&lt;&gt; 无法影响该集合。当您尝试将错误类型的变量分配给该变体时,您将收到编译时错误。
  • @MSalters:但是,如果您阅读了这个问题,那正是 myWallJSON 所要求的。我回答了。
猜你喜欢
  • 2011-01-04
  • 1970-01-01
  • 2011-02-09
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多