Boost.Variant,Boost.MPL:如何追加类型? [英] Boost.Variant, Boost.MPL: How to append types?

查看:138
本文介绍了Boost.Variant,Boost.MPL:如何追加类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看基于boost.Any 并不能帮助这个篦code,但不知道是否我们可以使用 Boost.Variant 代替。我不知道如果这样的API将是可能的:

 无效voidFunc()
{
    性病::法院LT&;< 虚空称为<<的std :: ENDL;
}INT stringFunc(性病::字符串str)
{
    性病::法院LT&;< STR<<的std :: ENDL;
    返回0;
}诠释的main()
{
    some_map_like_type<的std ::字符串,提振::变种> funcs中;
    funcs.insert<无效,无效>(voidFunc,&安培; voidFunc)); //现在我们的变种vould包含类似的boost ::功能<无效,无效>
    funcs.insert< INT,标准::字符串>(stringFunc,&安培; stringFunc)); //现在我们加入到我们的变种一个新的类型:升压::功能< INT,标准::字符串>
    funcs.insert<无效,无效>(voidFunc2,&安培; voidFunc)); //现在我们的变种不应该改变,因为它已经包含提高::功能<无效,无效>类型
    //这里当所有有趣的部分是:
    funcs中[voidFunc](); //编译
    funcs中[stringFunc(你好); //编译
    funcs中[stringFunc](some_not_std_string_class); //不能编译。
    返回0;
}

这意味着,在最后编译器必须编译是这样的:

 无效voidFunc()
{
    性病::法院LT&;< 虚空称为<<的std :: ENDL;
}INT stringFunc(性病::字符串str)
{
    性病::法院LT&;< STR<<的std :: ENDL;
    返回0;
}诠释的main()
{
    some_map_like_type<的std ::字符串,提振::变体LT;提振::函数<无效,无效>中的boost ::功能< INT,标准::字符串> > > funcs中;
    funcs.insert<无效,无效>(voidFunc,&安培; voidFunc)); //现在我们的变种vould包含类似的boost ::功能<无效,无效>
    funcs.insert< INT,标准::字符串>(stringFunc,&安培; stringFunc)); //现在我们加入到我们的变种一个新的类型:升压::功能< INT,标准::字符串>
    funcs.insert<无效,无效>(voidFunc2,&安培; voidFunc)); //现在我们的变种不应该改变,因为它已经包含提高::功能<无效,无效>类型
    //这里当所有有趣的部分是:
    funcs中[voidFunc](); //编译
    funcs中[stringFunc(你好); //编译
    funcs中[stringFunc](some_not_std_string_class); //这里会给错误并不会编译
    返回0;
}

更新:

有什么我想(在此基础上变异文档 MPL演示和<一个HREF =htt​​p://www.boost.org/doc/libs/1_47_0/libs/mpl/doc/refmanual/vector.html相对=nofollow>文档):

 的#include&LT;升压/ static_assert.hpp&GT;
#包括LT&;提升/ MPL / equal.hpp&GT;
#包括LT&;提升/ MPL / vector_c.hpp&GT;
#包括LT&;提升/ MPL / transform.hpp&GT;
#包括LT&;提升/ MPL / multiplies.hpp&GT;
#包括LT&;提升/ MPL / placeholders.hpp&GT;#包括LT&;升压/ variant.hpp&GT;
#包括LT&;&iostream的GT;
#包括LT&;串GT;
#包括LT&;矢量&GT;类sudo_science
{
上市:
    TYPEDEF提振:: MPL :: vector_c&LT; INT&GT; types_vector1;    TYPEDEF提振:: make_recursive_variant&LT; types_vector1&GT; ::类型recursive_variant_t;    的std ::矢量&lt; recursive_variant_t&GT; variant_seq;    模板&LT; typename的T&GT;
    无效追加(T VAL)
    {
        TYPEDEF提振:: MPL ::的push_back&LT; types_vector1,T&GT; ::类型types_vector1;
        variant_seq.push_back(VAL);
        返回;
    }    的std ::矢量&lt; recursive_variant_t&GT; give_me_end_variant()
     {
         返回variant_seq;
     }
};诠释的main()
{
    sudo_science一个;
    a.append&LT;浮动&GT;(1.0);
    a.append&LT;标准::字符串&GT;(协议栈和升压);    //对不起C ++ 11
    汽车varint = a.give_me_end_variant();    返回0;
}

但它失败2同样的错误编译:

 错误1错误C2665: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' :没有2重载可以转换所有的参数类型C:\\ Program Files文件\\提升\\ \\包括升压\\变种\\ variant.hpp 1330年1


解决方案

这是不可能的。 运算符[] 是一个运行时的事情,而类型是一个编译时的事情。因此,应该在编译器编译下面?

 字符常量*海峡;
如果(some_condition())
  海峡=voidFunc;
其他
  海峡=stringFunc;
// ...一些code
如果(some_condition())
  funcs中[STR]();
其他
  funcs中[STR](STR);

如何编译器应该知​​道是否第二次调用some_condition()像以前一样得到相同的结果呢?或两者之间的code是否修改 STR

价值

有关以下内容:

 无效调用(some_map_like_type&LT;的std ::字符串,提振::变种&GT;常量和放大器; funcs中)
{
  funcs中[voidFunc]();
}

编译器应该是怎样知道是否在通话时间 funcs中有一个条目映射voidFunc来一不带参数的功能?并应与不值发生什么,如果它与做了值调用一次,并一次?

根据你的真正的想要实现的,有可能是一种用模板来得到它, constexpr 功能。但是请注意,这没有任何发生在运行时可能会影响code是否编译,原因很简单,它被编译之前,code不能运行。

I look at this grate code based on boost.Any and cant help but wonder if we could use Boost.Variant instead. I wonder if such API would be possible:

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;
}

That means that at the end compiler would have to compile something like:

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;
}

Update:

What have I tried (based on this Variant docs and this MPL demos and docs):

#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;
}

But it fails to compile with 2 same errors:

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

解决方案

It is not possible. operator[] is a run-time thing, while types are a compile-time thing. So should the compiler compile the following?

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

How is the compiler supposed to know whether the second call to some_condition() gives the same result as before? Or whether the code in between modified the value of str?

What about the following:

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

How is the compiler supposed to know whether at call time funcs contains an entry mapping "voidFunc"to a function with no arguments? And what should happen if it is called once on with a value that does, and once with a value which doesn't?

Depending on what you actually want to achieve, there might be a way to get it with templates and constexpr functions. However note that nothing which happens at runtime can affect whether the code compiles, for the simple reason that the code cannot be run before it is compiled.

这篇关于Boost.Variant,Boost.MPL:如何追加类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆