结果为Boost和std的问题,一些在gcc中编译而在msvc中失败,反之亦然

时间:2014-11-30 07:56:02

标签: c++ templates c++11 boost

我想问一下是否有人知道为什么以下提供的示例代码在以下情况下无法编译:
1)MSVC 2013 with boost
2)GCC与-std = c ++ 11

相同的代码编译精细
1)在MSVC中,当boost :: result_of与std等效的一个交换时 2)在GCC中,当-std = c ++ 11标志未启用时,它编译正常。如果使用std :: result_of启用它没有帮助。

我很疑惑为什么会出现这样的错误,所以我想说清楚。

下面的类是尽可能少的,我可以让它重现我自己,所以它在使用中可能没有多大意义,但它显示了编译器错误。

#include <cstdint> // or #include <boost/cstdint.hpp>
#include <vector>
//#include <type_traits> // for C11
#include <boost/type_traits.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/static_assert.hpp> // if C11 is not enabled for static assert

template <class SrcT, class DstT>
struct CopyCVR
{
    typedef typename boost::remove_reference<SrcT>::type base_src;
    typedef typename boost::remove_cv<typename boost::remove_reference<DstT>::type>::type base_dst;
    typedef typename boost::mpl::if_< boost::is_volatile<base_src>, volatile base_dst, base_dst >::type v_dst;
    typedef typename boost::mpl::if_< boost::is_const<base_src>, const v_dst, v_dst >::type cv_dst;
    typedef typename boost::mpl::if_< boost::is_reference<SrcT>, cv_dst&, cv_dst >::type type;
};

template <class typeT>
class Element2
{
    typeT elem[2];
public:
    typedef typeT elemType;

    Element2() { elem[0] = elem[1] = 0; }
    typeT& operator[](size_t i) { return elem[i]; }
};

template <class elementT>
class List
{
    std::vector<elementT> m_List;
public:
    typedef elementT list_type;
    typedef elementT& result_type;

    List() {};
    result_type operator[](size_t i) { return m_List[i]; }
    void Add(const elementT& el) { this->m_List.push_back(el); }
};

template <class ResultT, class typeT>
inline ResultT select(typeT& elem, int32_t num)
{
    return elem[num];
}

template <class List>
struct SelectFunctor
{
    int32_t m_elem;
public:
    SelectFunctor(int32_t elem) : m_elem(elem) {}

    typedef typename List::list_type::elemType listElem_type;
    typedef typename CopyCVR<typename List::result_type, listElem_type>::type result_type;

    result_type operator()(typename List::result_type elem) const
    {
        return select<result_type>(elem, m_elem);
    }
};

以下是使用上述类的代码示例。

int main(int argc, _TCHAR* argv[])
{
    typedef List<Element2<double>> ListDouble;
    ListDouble list;
    SelectFunctor<ListDouble> sel(1);
    list.Add(Element2<double>());
    double val = sel(list[0]);

    #if 1 // this return a compiler error
    typedef boost::result_of< SelectFunctor<ListDouble>(typename ListDouble::list_type)>::type result_type;
    #else // this is OK
    typedef std::result_of< SelectFunctor<ListDouble>(typename ListDouble::list_type)>::type result_type;
    #endif
    static_assert(std::is_same<result_type, double&>::value, "Error");
}

在MSVC + boost的情况下,编译器错误是 错误C2039:'type':不是'boost :: result_of(Element2)&gt;'的成员

在GCC中,我可以使用boost进行编译,检查示例代码和编译结果 http://coliru.stacked-crooked.com/a/a80c29d736437eab
但是,如果在-std = c ++ 11中启用C11并且没有代码更改则失败。在这种情况下提到甚至交换boost :: result_of与std等效的一个没有帮助。类似的编译错误记录在 http://coliru.stacked-crooked.com/a/629ee3cdb9376376

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

typedef boost::result_of<SelectFunctor<ListDouble>(typename ListDouble::list_type &) >::type result_type;
//                                                                                ^

SelectFunctor的函数调用运算符需要typename List::result_type,这是elementT&的别名。您的result_of询问是否可以使用typename ListDouble::list_typetypename是不必要的,BTW)来调用它,elementT

无法使用右值elementT调用仿函数,因为您无法将非常量左值引用绑定到右值。因此,result_of中没有type嵌套的typedef。