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

C++ Boost和std问题的结果,一些在gcc中编译,而在msvc中失败,反之亦然,c++,templates,c++11,boost,C++,Templates,C++11,Boost,我想问一下,是否有人知道为什么下面提供的示例代码在某些情况下无法编译: 1) MSVC 2013与boost的合作 2) 带-std=c++11的GCC 同样的代码编译得很好 1) 在MSVC中,当的boost::result_与std等效值交换时 2) 在GCC中,当未启用-std=c++11标志时,它可以正常编译。在这种情况下,使用std::result_of启用它没有帮助 我很困惑为什么我会犯这样的错误,所以我想解释一下 下面的类尽可能少,我可以让它重现我自己的类,所以它在使用中可能没有多

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

同样的代码编译得很好
1) 在MSVC中,当的boost::result_与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);
    }
};
#包括//或#包括
#包括
//#包括//用于C11
#包括
#包括
#包含//如果未为静态断言启用C11
样板
结构CopyCVR
{
typedef typename boost::remove_reference::type base_src;
typedef typename boost::remove_cv::type base_dst;
typedef typename boost::mpl::if_u::type v_dst;
typedef typename boost::mpl::if_uu::键入cv_dst;
typedef typename boost::mpl::if_uu::type;
};
样板
类元素2
{
类型元素[2];
公众:
typedef typeT elemType;
Element2(){elem[0]=elem[1]=0;}
typeT&运算符[](size_t i){return elem[i];}
};
样板
班级名单
{
std::向量m_列表;
公众:
类型定义元素列表\u类型;
类型定义元素T和结果_类型;
列表(){};
结果_类型运算符[](大小_t i){返回m_列表[i];}
void Add(const elementT&el){this->m_List.push_back(el);}
};
样板
内联结果选择(类型和元素,整数)
{
返回元素[num];
}
样板
结构选择函子
{
int32_t m_elem;
公众:
选择函子(int32元素):m元素(元素){}
typedef typename List::List_type::elemType listElem_type;
typedef typename CopyCVR::type result\u 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");
}
int main(int argc,_TCHAR*argv[]
{
typedef列表列表;
列表双列表;
选择函子sel(1);
添加(Element2());
双val=sel(列表[0]);
#如果1//,则返回编译器错误
:type result_type的typedef boost::result_;
#否则,这没关系
:type result_type的typedef std::result_;
#恩迪夫
静态断言(std::is_same::value,“Error”);
}
在MSVC+boost的情况下,编译器错误为 错误C2039:“类型”:不是“boost::result_of(Element2)>”的成员

在GCC中,我可以使用boost进行编译,在

但是,如果您在-std=c++11中启用C11,并且没有代码更改,则会失败。在这种情况下,如前所述,即使将的boost::result_替换为std等效值也无济于事。在

有什么想法吗?

typedef boost::result\u of::type result\u type;
typedef boost::result_of<SelectFunctor<ListDouble>(typename ListDouble::list_type &) >::type result_type;
//                                                                                ^
// ^
SelectFunctor
的函数调用操作符采用
typename List::result\u type
,它是
elementT&
的别名。您的
结果\u的
查询是否可以使用
typename list double::list\u type调用它(顺便说一句,
typename
是不必要的),即
elementT


不能使用右值
元素t
调用函子,因为不能将非常量左值引用绑定到右值。因此,
result_中没有
type
嵌套的typedef。这是有道理的,但是,您能否提供一些评论,说明为什么在某些情况下,它编译得很好,没有任何问题?我希望std和boost的结果_的实现非常相似,但std很好。此外,当C11编译标志丢失时,为什么GCC可以呢?编译器也应该将其标记为错误,但它是合格的,并且类型设置正确(或不正确?)@xerion有两种不同的“操作模式”,这取决于编译器是否对
decltype
有足够的支持。当您使用boost 1.52或更高版本,并且在c++11模式下拥有足够现代的编译器时,它只需使用decltype,并返回函数/函子在传递确切参数时返回的确切类型。在其他情况下,它使用协议的tr1结果,该协议包括定义
结果类型
或内部
结果
结构。您可以使用BOOST\u RESULT\u OF\u USE\u TR1.Aha强制最后一种模式,然后我的理解是正确的,即使用
RESULT\u type
方法会丢失限定符,而
decltype
更能返回准确的类型。我想这就解释了为什么在启用C11时GCC会失败,因为boost使用了
decltype
。我原以为std::result\u of也会以类似的方式运行,但我有一个奇怪的外观,似乎在msvc中它是在不使用
decltype
@xerion的情况下实现的,如果您使用可以使用的result\u-type方法(int-TR1模式),它仍然会返回
double&
。“结果类型”方法意味着结果不依赖于参数,并且总是相同的(这在我之前评论的链接中解释)。@cv_和_他感谢您指出OP查询的真实答案。你可以考虑发布一个(社区wiki)的答案: