2017-06-15 69 views
2

以下示例代码:与拉姆达升压算法编译失败

#define BOOST_RESULT_OF_USE_DECLTYPE // does not help 

#include <vector> 
#include <algorithm> 
#include <future> 
#include <boost/range/algorithm.hpp> 

struct DW { 
    std::promise<bool> success_; 
}; 

template <class T> 
class Pool 
{ 
public: 
    Pool() : container_{} 
    {}; 
public: 
    typename std::vector<T>::iterator begin() { return container_.begin(); } 
    typename std::vector<T>::iterator end() { return container_.end(); } 
    typename std::vector<T>::const_iterator begin() const { return container_.begin(); } 
    typename std::vector<T>::const_iterator end() const { return container_.end(); } 
private: 
    std::vector<T>  container_;  ///< holder of elements 
}; 

#define LAMBDA [] (DW& w) { return w.success_.get_future().get(); } 

int main() 
{ 
    Pool<DW> vec; 

    auto s = std::count_if(vec.begin(), vec.end(), LAMBDA); 
    auto b = boost::count_if(vec, LAMBDA); 

    return (s == b) ? 0 : 1; 
} 

失败GCC 4.8.5,6.2或8至编译:

g++ -g -pthread -std=gnu++0x -Wall -pedantic -Wextra -Wformat=2 -o "ranger" "ranger.cpp" (in directory: /tmp) 
In file included from /usr/local/include/boost/iterator/iterator_categories.hpp:15:0, 
       from /usr/local/include/boost/iterator/iterator_concepts.hpp:10, 
       from /usr/local/include/boost/range/concepts.hpp:20, 
       from /usr/local/include/boost/range/algorithm.hpp:29, 
       from ranger.cpp:6: 
/usr/local/include/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if_c<false, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<Pool<DW>, void> >’: 
/usr/local/include/boost/range/iterator.hpp:69:17: required from ‘struct boost::range_iterator<Pool<DW>, void>’ 
/usr/local/include/boost/range/difference_type.hpp:26:12: required from ‘struct boost::range_difference<Pool<DW> >’ 
/usr/local/include/boost/range/algorithm/count_if.hpp:32:1: required by substitution of ‘template<class SinglePassRange, class UnaryPredicate> typename boost::range_difference<T>::type boost::range::count_if(SinglePassRange&, UnaryPredicate) [with SinglePassRange = Pool<DW>; UnaryPredicate = main()::__lambda5]’ 
ranger.cpp:34:41: required from here 
/usr/local/include/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<false, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<Pool<DW>, void> >::f_ {aka struct boost::range_mutable_iterator<Pool<DW>, void>}’ 
    typedef typename f_::type type; 
          ^
/usr/local/include/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if_c<true, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<const Pool<DW>, void> >’: 
/usr/local/include/boost/range/iterator.hpp:69:17: required from ‘struct boost::range_iterator<const Pool<DW>, void>’ 
/usr/local/include/boost/range/difference_type.hpp:26:12: required from ‘struct boost::range_difference<const Pool<DW> >’ 
/usr/local/include/boost/range/algorithm/count_if.hpp:41:1: required by substitution of ‘template<class SinglePassRange, class UnaryPredicate> typename boost::range_difference<const SinglePassRange>::type boost::range::count_if(const SinglePassRange&, UnaryPredicate) [with SinglePassRange = Pool<DW>; UnaryPredicate = main()::__lambda5]’ 
ranger.cpp:34:41: required from here 
/usr/local/include/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<const Pool<DW>, void> >::f_ {aka struct boost::range_const_iterator<Pool<DW>, void>}’ 
ranger.cpp: In function ‘int main()’: 
ranger.cpp:34:41: error: no matching function for call to ‘count_if(Pool<DW>&, main()::__lambda5)’ 
    auto b = boost::count_if(vec, LAMBDA); 
             ^
ranger.cpp:34:41: note: candidates are: 
In file included from /usr/local/include/boost/range/algorithm.hpp:40:0, 
       from ranger.cpp:6: 
/usr/local/include/boost/range/algorithm/count_if.hpp:41:1: note: template<class SinglePassRange, class UnaryPredicate> typename boost::range_difference<const SinglePassRange>::type boost::range::count_if(const SinglePassRange&, UnaryPredicate) 
count_if(const SinglePassRange& rng, UnaryPredicate pred) 
^ 
/usr/local/include/boost/range/algorithm/count_if.hpp:41:1: note: substitution of deduced template arguments resulted in errors seen above 
/usr/local/include/boost/range/algorithm/count_if.hpp:32:1: note: template<class SinglePassRange, class UnaryPredicate> typename boost::range_difference<T>::type boost::range::count_if(SinglePassRange&, UnaryPredicate) 
count_if(SinglePassRange& rng, UnaryPredicate pred) 
^ 
/usr/local/include/boost/range/algorithm/count_if.hpp:32:1: note: substitution of deduced template arguments resulted in errors seen above 
Compilation failed. 

并且还与铛5.0.0(树干302784)

$ clang++ -g -pthread -std=c++14 -Wall -pedantic -Wextra -Wformat=2 -o "ranger" "ranger.cpp" (in directory: /tmp) 
In file included from ranger.cpp:6: 
In file included from /usr/local/include/boost/range/algorithm.hpp:29: 
In file included from /usr/local/include/boost/range/concepts.hpp:20: 
In file included from /usr/local/include/boost/iterator/iterator_concepts.hpp:10: 
In file included from /usr/local/include/boost/iterator/iterator_categories.hpp:15: 
/usr/local/include/boost/mpl/eval_if.hpp:60:26: error: no type named 'type' in 'boost::range_mutable_iterator<Pool<DW>, void>' 
    typedef typename f_::type type; 
      ~~~~~~~~~~~~~^~~~ 
/usr/local/include/boost/range/iterator.hpp:65:31: note: in instantiation of template class 'boost::mpl::eval_if_c<false, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<Pool<DW>, void> >' requested here 
     typedef typename mpl::eval_if_c< 
          ^
/usr/local/include/boost/range/difference_type.hpp:28:40: note: in instantiation of template class 'boost::range_iterator<Pool<DW>, void>' requested here 
       BOOST_DEDUCED_TYPENAME range_iterator< 
            ^
/usr/local/include/boost/range/algorithm/count_if.hpp:31:38: note: in instantiation of template class 'boost::range_difference<Pool<DW> >' requested here 
inline BOOST_DEDUCED_TYPENAME boost::range_difference<SinglePassRange>::type 
            ^
ranger.cpp:34:14: note: while substituting deduced template arguments into function template 'count_if' [with SinglePassRange = Pool<DW>, UnaryPredicate = (lambda at ranger.cpp:34:35)] 
    auto b = boost::count_if(vec, LAMBDA); 
      ^
In file included from ranger.cpp:6: 
In file included from /usr/local/include/boost/range/algorithm.hpp:29: 
In file included from /usr/local/include/boost/range/concepts.hpp:20: 
In file included from /usr/local/include/boost/iterator/iterator_concepts.hpp:10: 
In file included from /usr/local/include/boost/iterator/iterator_categories.hpp:15: 
/usr/local/include/boost/mpl/eval_if.hpp:60:26: error: no type named 'type' in 'boost::range_const_iterator<Pool<DW>, void>' 
    typedef typename f_::type type; 
      ~~~~~~~~~~~~~^~~~ 
/usr/local/include/boost/range/iterator.hpp:65:31: note: in instantiation of template class 'boost::mpl::eval_if_c<true, boost::range_const_iterator<Pool<DW>, void>, boost::range_mutable_iterator<const Pool<DW>, void> >' requested here 
     typedef typename mpl::eval_if_c< 
          ^
/usr/local/include/boost/range/difference_type.hpp:28:40: note: in instantiation of template class 'boost::range_iterator<const Pool<DW>, void>' requested here 
       BOOST_DEDUCED_TYPENAME range_iterator< 
            ^
/usr/local/include/boost/range/algorithm/count_if.hpp:40:38: note: in instantiation of template class 'boost::range_difference<const Pool<DW> >' requested here 
inline BOOST_DEDUCED_TYPENAME boost::range_difference<const SinglePassRange>::type 
            ^
ranger.cpp:34:14: note: while substituting deduced template arguments into function template 'count_if' [with SinglePassRange = Pool<DW>, UnaryPredicate = (lambda at ranger.cpp:34:35)] 
    auto b = boost::count_if(vec, LAMBDA); 
      ^
ranger.cpp:34:14: error: no matching function for call to 'count_if' 
    auto b = boost::count_if(vec, LAMBDA); 
      ^~~~~~~~~~~~~~~ 
/usr/local/include/boost/range/algorithm/count_if.hpp:32:1: note: candidate template ignored: substitution failure [with SinglePassRange = Pool<DW>, UnaryPredicate = (lambda at ranger.cpp:34:35)] 
count_if(SinglePassRange& rng, UnaryPredicate pred) 
^ 
/usr/local/include/boost/range/algorithm/count_if.hpp:41:1: note: candidate template ignored: substitution failure [with SinglePassRange = Pool<DW>, UnaryPredicate = (lambda at ranger.cpp:34:35)] 
count_if(const SinglePassRange& rng, UnaryPredicate pred) 
^ 
3 errors generated. 
Compilation failed. 

是不是boost::algo(range)应该是一个下拉更换为std::algo(range.begin(), range.end())

+0

那么,它是否适用于普通的老'矢量'?如何使用简单的lambda'[](int x){return x%2;''vector ''? 'Pool '?不是由宏生成的lambda?我想知道你需要什么相对复杂的设置。 – Yakk

+0

看起来像是在像''difference_type''这样的'Pool'中丢失了特定的typedef。 – NathanOliver

+0

@NathanOliver我在想那个;但如果boost并不吸引,它应该能够从'decltype(std :: declval ().begin())'和'iterator_traits'推导出这些东西吗?我对这个特定的boost API不太熟悉,但我试着假设最好的API。 – Yakk

回答

6

在您的Pool类中定义iteratorconst_iterator。 Boost算法库是在C++ 11之前编写的,它不使用decltype来找出迭代器类型。不幸的是,它仍然没有更新,如果可用,所以你必须定义迭代器类型。无论如何,这是一个很好的做法。

template <class T> 
class Pool 
{ 
public: 
    Pool() : container_{} 
    {}; 
public: 
    using iterator = typename std::vector<T>::iterator; 
    using const_iterator = typename std::vector<T>::const_iterator; 

    iterator begin() { return container_.begin(); } 
    iterator end() { return container_.end(); } 
    const_iterator begin() const { return container_.begin(); } 
    const_iterator end() const { return container_.end(); } 
private: 
    std::vector<T>  container_;  ///< holder of elements 
}; 
+2

您可以进一步定义C++标准容器通常具有的无数类型定义:http://en.cppreference.com/w/cpp/container/forward_list - 转发列表的集合相当简单。它们中的大多数与您可以从'std :: iterator_traits '得到的结果完全相同。 – Yakk

+0

宾果! 'iterator'和'const_iterator'都是需要的。 – Bulletmagnet