Build rtree with boost::geometry results in errors - c++

I wrote this small program, following the boost documentation, but I get pages of errors when building it.
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::d2::point_xy<double> point_2d;
class Foo
{
public:
point_2d position;
Foo(double x, double y) : position(x, y) {}
auto get() const { return position; }
};
int main()
{
bgi::rtree<Foo, bgi::quadratic<16>> rtree;
rtree.insert(Foo(1.0, 2.0));
rtree.insert(Foo(3.0, 4.0));
rtree.insert(Foo(5.0, 6.0));
rtree.insert(Foo(7.0, 8.0));
// Define a search box with a certain distance from a given point
point_2d search_point(0.0, 0.0);
double search_distance = 5.0;
point_2d lower_left(search_point.x() - search_distance, search_point.y() - search_distance);
point_2d upper_right(search_point.x() + search_distance, search_point.y() + search_distance);
bg::model::box<point_2d> search_box(lower_left, upper_right);
// Use the rtree to search for instances of Foo within the search box
std::vector<Foo> result;
rtree.query(bgi::intersects(search_box), std::back_inserter(result));
// Print the results
std::cout << "Found " << result.size() << " instances of Foo within the search box" << std::endl;
for (const auto& foo : result)
std::cout << "Foo at position (" << foo.position.x() << ", " << foo.position.y() << ")" << std::endl;
}
Here is the build:
clang++ --std=c++17 tree.cpp -lboost-geometry 2>&1 | head -n50
In file included from tree.cpp:1:
In file included from /usr/include/boost/geometry/index/rtree.hpp:49:
/usr/include/boost/geometry/index/indexable.hpp:64:5: error: no matching function for call to 'assertion_failed'
BOOST_MPL_ASSERT_MSG(
^~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:454:51: note: expanded from macro 'BOOST_MPL_ASSERT_MSG'
# define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \
^
/usr/include/boost/mpl/assert.hpp:440:9: note: expanded from macro '\
BOOST_MPL_ASSERT_MSG_IMPL'
boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:60:58: note: expanded from macro '\
BOOST_MPL_AUX_ASSERT_CONSTANT'
# define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
^~~~
/usr/include/boost/geometry/index/indexable.hpp:351:7: note: in instantiation of template class 'boost::geometry::index::detail::indexable<Foo, false>' requested here
: detail::indexable<Value>
^
/usr/include/boost/geometry/index/detail/translator.hpp:46:14: note: in instantiation of template class 'boost::geometry::index::indexable<Foo>' requested here
: public IndexableGetter
^
/usr/include/boost/geometry/index/detail/translator.hpp:74:22: note: in instantiation of template class 'boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> >' requested here
typedef typename IndexableGetter::result_type type;
^
/usr/include/boost/geometry/index/detail/translator.hpp:82:22: note: in instantiation of template class 'boost::geometry::index::detail::result_type<boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> > >' requested here
typename result_type<IndexableGetter>::type
^
/usr/include/boost/geometry/index/rtree.hpp:177:37: note: in instantiation of template class 'boost::geometry::index::detail::indexable_type<boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> > >' requested here
typedef typename index::detail::indexable_type<
^
tree.cpp:27:41: note: in instantiation of template class 'boost::geometry::index::rtree<Foo, boost::geometry::index::quadratic<16, 4>, boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo>, boost::container::new_allocator<Foo> >' requested here
bgi::rtree<Foo, bgi::quadratic<16>> rtree;
^
/usr/include/boost/mpl/assert.hpp:83:5: note: candidate function template not viable: no known conversion from 'boost::mpl::failed ************(boost::geometry::index::detail::indexable<Foo, false>::NOT_VALID_INDEXABLE_TYPE::************)(Foo)' to 'typename assert<false>::type' (aka 'mpl_::assert<false>') for 1st argument
int assertion_failed( typename assert<C>::type );
^
In file included from tree.cpp:1:
In file included from /usr/include/boost/geometry/index/rtree.hpp:28:
In file included from /usr/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:23:
In file included from /usr/include/boost/geometry/geometries/concepts/check.hpp:28:
In file included from /usr/include/boost/geometry/geometries/concepts/box_concept.hpp:23:
In file included from /usr/include/boost/geometry/core/access.hpp:25:
In file included from /usr/include/boost/geometry/core/coordinate_type.hpp:20:
/usr/include/boost/geometry/core/point_type.hpp:45:5: error: no matching function for call to 'assertion_failed'
BOOST_MPL_ASSERT_MSG
^~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:454:51: note: expanded from macro 'BOOST_MPL_ASSERT_MSG'
# define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \

Foo is not an indexable type. Meaning, mainly, that rtree doesn't know what geometry to index it by.
Let's make an IndexableGetter:
struct ByPos {
using result_type = point_2d;
result_type const& operator()(Foo const& f) const { return f.position; }
};
Now you can use it:
Live On Coliru
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
using point_2d = bg::model::d2::point_xy<double> ;
using box = bg::model::box<point_2d>;
struct Foo {
point_2d position;
Foo(double x, double y) : position(x, y) {}
auto get() const { return position; }
struct ByPos {
using result_type = point_2d;
result_type const& operator()(Foo const& f) const { return f.position; }
};
};
auto intersecting(auto const& search, auto const& tree) {
std::vector<std::reference_wrapper<Foo const>> result;
tree.query(bgi::intersects(search), back_inserter(result));
return result;
}
int main() {
bgi::rtree<Foo, bgi::quadratic<16>, Foo::ByPos> rtree;
rtree.insert({1.0, 2.0});
rtree.insert({3.0, 4.0});
rtree.insert({5.0, 6.0});
rtree.insert({7.0, 8.0});
// box with given distance from center
auto makebox = [&](double d, point_2d c = {}) {
return box{{c.x() - d, c.y() - d}, {c.x() + d, c.y() + d}};
};
auto key = makebox(5.0);
std::cout << "Within " << bg::dsv(key) << ":\n";
for (Foo const& foo : intersecting(key, rtree))
std::cout << " - at " << bg::dsv(foo.position) << "\n";
}
Prints
Within ((-5, -5), (5, 5)):
- at (1, 2)
- at (3, 4)

Related

what is the way to remove the first element from a std::span<T>?

when reading the document of std::span, I see there is no method to remove the first element from the std::span<T>.
Can you suggest a way to solve my issue?
The large picture of my problem(I asked in another question: How to instantiatiate a std::basic_string_view with custom class T, I got is_trivial_v<_CharT> assert error) is that I would like to have a std::basic_string_view<Token>, while the Token is not a trivial class, so I can't use std::basic_string_view, and someone suggested me to use std::span<Token> instead.
Since the basic_string_view has a method named remove_prefix which remove the first element, while I also need such kinds of function because I would like to use std::span<Token> as a parser input, so the Tokens will be matched, and consumed one by one.
Thanks.
EDIT 2023-02-04
I try to derive a class named Span from std::span, and add the remove_prefix member function, but it looks like I still have build issues:
#include <string_view>
#include <vector>
#include <span>
// derived class, add remove_prefix function to std::span
template<typename T>
class Span : public std::span<T>
{
public:
// Inheriting constructors
using std::span<T>::span;
// add a public function which is similar to std::string_view::remove_prefix
constexpr void remove_prefix(std::size_t n) {
*this = subspan(n);
}
};
struct Token
{
Token(){};
Token(const Token& other)
{
lexeme = other.lexeme;
type = other.type;
}
std::string_view lexeme;
int type;
// equal operator
bool operator==(const Token& other)const {
return (this->lexeme == other.lexeme) ;
}
};
template <typename T>
struct Viewer;
template <>
struct Viewer<Token>
{
using type = Span<Token>; // std::span or derived class
};
template <>
struct Viewer<char>
{
using type = std::string_view;
};
template <typename T> using ViewerT = typename Viewer<T>::type;
template <typename T>
class Parser
{
using v = ViewerT<T>;
};
// a simple parser demo
template <typename Base, typename T>
struct parser_base {
using v = ViewerT<T>;
constexpr auto operator[](v& output) const noexcept;
};
template<typename T>
struct char_ final : public parser_base<char_<T>, T> {
using v = ViewerT<T>;
constexpr explicit char_(const T ch) noexcept
: ch(ch)
{}
constexpr inline bool visit(v& sv) const& noexcept {
if (!sv.empty() && sv.front() == ch) {
sv.remove_prefix(1);
return true;
}
return false;
}
private:
T ch;
};
template <typename Parser, typename T>
constexpr bool parse(Span<T> &input, Parser const& parser) noexcept {
return parser.visit(input);
}
int main()
{
Token kw_class;
kw_class.lexeme = "a";
std::vector<Token> token_stream;
token_stream.push_back(kw_class);
token_stream.push_back(kw_class);
token_stream.push_back(kw_class);
Span<Token> token_stream_view{&token_stream[0], 3};
auto p = char_(kw_class);
parse(token_stream_view, p);
return 0;
}
The build error looks like below:
[ 50.0%] g++.exe -Wall -std=c++20 -fexceptions -g -c F:\code\test_crtp_twoargs\main.cpp -o obj\Debug\main.o
F:\code\test_crtp_twoargs\main.cpp: In member function 'constexpr void Span<T>::remove_prefix(std::size_t)':
F:\code\test_crtp_twoargs\main.cpp:52:17: error: there are no arguments to 'subspan' that depend on a template parameter, so a declaration of 'subspan' must be available [-fpermissive]
52 | *this = subspan(n);
| ^~~~~~~
F:\code\test_crtp_twoargs\main.cpp:52:17: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
F:\code\test_crtp_twoargs\main.cpp: In instantiation of 'constexpr void Span<T>::remove_prefix(std::size_t) [with T = Token; std::size_t = long long unsigned int]':
F:\code\test_crtp_twoargs\main.cpp:113:29: required from 'constexpr bool char_<T>::visit(v&) const & [with T = Token; v = Span<Token>]'
F:\code\test_crtp_twoargs\main.cpp:125:24: required from 'constexpr bool parse(Span<T>&, const Parser&) [with Parser = char_<Token>; T = Token]'
F:\code\test_crtp_twoargs\main.cpp:141:10: required from here
F:\code\test_crtp_twoargs\main.cpp:52:24: error: 'subspan' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
52 | *this = subspan(n);
| ~~~~~~~^~~
F:\code\test_crtp_twoargs\main.cpp:52:24: note: declarations in dependent base 'std::span<Token, 18446744073709551615>' are not found by unqualified lookup
F:\code\test_crtp_twoargs\main.cpp:52:24: note: use 'this->subspan' instead
F:\code\test_crtp_twoargs\main.cpp:52:15: error: no match for 'operator=' (operand types are 'Span<Token>' and 'std::span<Token, 18446744073709551615>')
52 | *this = subspan(n);
| ~~~~~~^~~~~~~~~~~~
F:\code\test_crtp_twoargs\main.cpp:44:7: note: candidate: 'constexpr Span<Token>& Span<Token>::operator=(const Span<Token>&)'
44 | class Span : public std::span<T>
| ^~~~
F:\code\test_crtp_twoargs\main.cpp:44:7: note: no known conversion for argument 1 from 'std::span<Token, 18446744073709551615>' to 'const Span<Token>&'
F:\code\test_crtp_twoargs\main.cpp:44:7: note: candidate: 'constexpr Span<Token>& Span<Token>::operator=(Span<Token>&&)'
F:\code\test_crtp_twoargs\main.cpp:44:7: note: no known conversion for argument 1 from 'std::span<Token, 18446744073709551615>' to 'Span<Token>&&'
Any idea on how to fix this issue?
Also, I don't know how to make a general parse function:
template <typename Parser, typename T>
constexpr bool parse(Span<T> &input, Parser const& parser) noexcept {
return parser.visit(input);
}
Currently, the first argument of the parse should be a Viewer like type?
EDIT2023-02-05
Change the function as below, the above code can build correctly. This is from Benjamin Buch's answer.
constexpr void remove_prefix(std::size_t n) {
auto& self = static_cast<std::span<T>&>(*this);
self = self.subspan(n);
}
There is still one thing remains: How to generalize the parse function to accept both input types of std::string_view and Span<Token>?
If I change the parse function to this:
template <typename Parser, typename T>
constexpr bool parse(ViewerT<T> &input, Parser const& parser) noexcept {
return parser.visit(input);
}
I got such compile error:
[ 50.0%] g++.exe -Wall -std=c++20 -fexceptions -g -c F:\code\test_crtp_twoargs\main.cpp -o obj\Debug\main.o
F:\code\test_crtp_twoargs\main.cpp: In function 'int main()':
F:\code\test_crtp_twoargs\main.cpp:143:24: error: no matching function for call to 'parse(Span<Token>&, char_<Token>&)'
143 | bool result = parse(token_stream_view, p);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~
F:\code\test_crtp_twoargs\main.cpp:125:16: note: candidate: 'template<class Parser, class T> constexpr bool parse(ViewerT<T>&, const Parser&)'
125 | constexpr bool parse(ViewerT<T> &input, Parser const& parser) noexcept {
| ^~~~~
F:\code\test_crtp_twoargs\main.cpp:125:16: note: template argument deduction/substitution failed:
F:\code\test_crtp_twoargs\main.cpp:143:24: note: couldn't deduce template parameter 'T'
143 | bool result = parse(token_stream_view, p);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~
Any ideas?
Thanks.
BTW: I have to explicitly instantiation of the parse function call like:
bool result = parse<decltype(p), Token>(token_stream_view, p);
to workaround this issue.
Call subspan with 1 as only (template) argument to get a new span, which doesn't contain the first element.
If you use a span with a static extend, you need a new variable because the data type changes by subspan.
#include <string_view>
#include <iostream>
#include <span>
int main() {
std::span<char const, 12> text_a("a test-span");
std::cout << std::string_view(text_a) << '\n';
std::span<char const, 10> text_b = text_a.subspan<2>();
std::cout << std::string_view(text_b) << '\n';
}
If you have a dynamic extend, you can assign the result to the original variable.
#include <string_view>
#include <iostream>
#include <span>
int main() {
std::span<char const> text("a test-span");
std::cout << std::string_view(text) << '\n';
text = text.subspan(2);
std::cout << std::string_view(text) << '\n';
}
The implementation of a modifying inplace subspan version is only possible for spans with a dynamic extend. It can be implemented as a free function.
#include <string_view>
#include <iostream>
#include <span>
template <typename T>
constexpr void remove_front(std::span<T>& self, std::size_t const n) noexcept {
self = self.subspan(n);
}
int main() {
std::span<char const> text("a test-span");
std::cout << std::string_view(text) << '\n';
remove_front(text, 2);
std::cout << std::string_view(text) << '\n';
}
You can use your own spans derived from std::span if you prefer the dot-call.
#include <string_view>
#include <iostream>
#include <span>
template <typename T>
struct my_span: std::span<T> {
using std::span<T>::span;
constexpr void remove_front(std::size_t const n) noexcept {
auto& self = static_cast<std::span<T>&>(*this);
self = self.subspan(n);
}
};
int main() {
my_span<char const> my_text("a test-span");
std::cout << std::string_view(my_text) << '\n';
my_text.remove_front(2);
std::cout << std::string_view(my_text) << '\n';
}
You can also write a wrapper class to call via dot syntax. This way you can additionally implement cascadable modification calls by always returning the a reference modifier class.
#include <string_view>
#include <iostream>
#include <span>
template <typename T>
class span_modifier {
public:
constexpr span_modifier(std::span<T>& span) noexcept: span_(span) {}
constexpr span_modifier& remove_front(std::size_t const n) noexcept {
span_ = span_.subspan(n);
return *this;
}
private:
std::span<T>& span_;
};
template <typename T>
constexpr span_modifier<T> modify(std::span<T>& span) noexcept {
return span;
}
int main() {
std::span<char const> text("a test-span");
std::cout << std::string_view(text) << '\n';
modify(text).remove_front(2).remove_front(5);
std::cout << std::string_view(text) << '\n';
}
Note I use the template function modify to create an object of the wrapper class, because the names of classes cannot be overloaded. Therefore class names should always be a bit more specific. The function modify can also be overloaded for other data types, which then return a different wrapper class. This results in a simple intuitive and consistent interface for modification wrappers.
You can write remove_prefix of your version,
template <typename T>
constexpr void remove_prefix(std::span<T>& sp, std::size_t n) {
sp = sp.subspan(n);
}
Demo

Unordered map hash function

#include <iostream>
#include <unordered_map>
#include <utility>
#include <cmath>
#include <stdint.h>
template <class T>
struct Vec2
{
T x, y;
Vec2() : x(0) , y(0) { };
Vec2(T xn, T yn) : x(xn), y(yn) { };
bool operator==(const Vec2& vec) const
{
return (x == vec.x) and (y == vec.y);
}
};
struct HashVec2int
{
const uint32_t maximum;
// HashVec2int(const uint32_t& m) : maximum(m) { }
std::size_t operator()(const Vec2<int>& vec) const
{ return (vec.x * maximum) + vec.y; }
};
int main() {
typedef Vec2<int> iVec2;
std::unordered_map<std::pair<iVec2, iVec2>,
float, HashVec2int{300}> umap;
umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))] = 3.14f;
std::cout << umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))];
return 0;
}
I want to initialize a hash function with a maximum x value to hash my implementation of vector.
I changed the struct to a class a couple of times and even marked maximum manually inside of HashVec2int. It gave me cryptic errors.
.\main.cpp:35:32: error: type/value mismatch at argument 3 in template parameter list for 'template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> class std::unordered_map'
float, HashVec2int{300}> umap;
^
.\main.cpp:35:32: note: expected a type, got 'HashVec2int{300u}'
.\main.cpp:37:6: error: no match for 'operator[]' (operand types are 'int' and 'std::pair<Vec2<int>, Vec2<int> >')
umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))] = 3.14f;
^
.\main.cpp:39:19: error: no match for 'operator[]' (operand types are 'int' and 'std::pair<Vec2<int>, Vec2<int> >')
std::cout << umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))];
^
I followed cppreference tutorials on how to create a modified hash function.
You have a map with keys of pairs of iVecs but your hash is for single iVecs, that doesnt match. Though this will only be the next error you will be getting after fixing the current one.
It seems you try to pass an instance HashVec2int{300} as template argument when a type is expected.
If maximum does not change (it should not for the hash to be consistent) you can do it like this:
template <uint32_t maximum>
struct HashVec2int
{
std::size_t operator()(const Vec2<int>& vec) const
{ return (vec.x * maximum) + vec.y; }
};
int main() {
typedef Vec2<int> iVec2;
std::unordered_map<iVec2,
float, HashVec2int<200>> umap;
umap[iVec2(1, 2)] = 3.14f;
std::cout << umap[iVec2(1, 2)];
return 0;
}
If you do not want to make HashVec2int a template you can still use it, then use its type Hashvec2Int as argument for the unordered map template and pass an instance, eg HashVec2Int{200}, to one of the constructors that takes a hash instance: https://en.cppreference.com/w/cpp/container/unordered_map/unordered_map

Generalizing input arguments for Eigen-types

The template guide provided by Eigen recommends using Eigen::MatrixBase to implicitly deduce template parameters to functions. In this example I want to pass an expression:
#include <iostream>
#include "Eigen/Dense"
template <typename D>
void eval(Eigen::MatrixBase<D>& in, Eigen::MatrixBase<D>& out)
{
out.array() = in.array() + 1;
}
int main()
{
Eigen::MatrixXd A(2,2);
A(0,0) = 2;
A(1,1) = 1;
Eigen::VectorXd B(2);
B(1) = 1;
std::cout << A << ", " << B << std::endl;
Eigen::VectorXd res(2);
eval(A*B, res);
std::cout << res << std::endl;
}
Which outputs an error:
EigenTest.cpp: In function ‘int main()’:
EigenTest.cpp:21:18: error: no matching function for call to ‘eval(const Eigen::Product<Eigen::Matrix<double, -1, -1>, Eigen::Matrix<double, -1, 1>, 0>, Eigen::VectorXd&)’
21 | eval(A*B, res);
Is there a more general form of Eigen::MatrixBase that extends to accepting expressions?
You have to use two template parameters and make the input reference refer to a const type. The issue is that the product operator will return a const value.
Like this
template <typename U, typename V>
void eval(const Eigen::MatrixBase<U>& in, Eigen::MatrixBase<V>& out)
{
out.array() = in.array() + 1;
}

g++: range-based for loop not compile without using namespace std;

The following code
#include <iostream>
#include <string>
using namespace std;
template <typename A> std::string to_string(const A& v) {
bool first = true;
std::string res = "{";
for (const auto &x : v) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(x);
}
res += "}";
return res;
}
void debug_out() { std::cerr << std::endl; }
template <typename Head, typename... Tail> void debug_out(const Head& H, const Tail&... T) {
std::cerr << " " << to_string(H);
debug_out(T...);
}
#define debug(...) std::cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
int main() {
int x = 3;
debug(x);
return 0;
}
complies with GCC 9.3.0 and outputs [x]: 3 when run. However, if the 3rd line using namespace std; is commented out, the code does not compile and the errors are
prog.cc: In instantiation of 'std::string to_string(const A&) [with A = int; std::string = std::__cxx11::basic_string<char>]':
prog.cc:21:32: required from 'void debug_out(const Head&, const Tail& ...) [with Head = int; Tail = {}]'
prog.cc:32:3: required from here
prog.cc:7:3: error: 'begin' was not declared in this scope; did you mean 'std::begin'?
7 | for (const auto &x : v) {
| ^~~
| std::begin
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:105:37: note: 'std::begin' declared here
105 | template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
| ^~~~~
prog.cc:7:3: error: 'end' was not declared in this scope; did you mean 'std::end'?
7 | for (const auto &x : v) {
| ^~~
| std::end
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:107:37: note: 'std::end' declared here
107 | template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
|
I know that a ranged-based for loop is not intended to be used on an integer, and the same code (either with or without using name space std;) does not compile with clang. However, why the statement using namespace std; makes a difference when complied with GCC?
You can check this on wandbox https://wandbox.org/permlink/kp5u1iMYHST83tCa .
The reason is that there exists a method to_string in namespace std. If you rename your method to my_to_string the error message will be independent from the using statement.

c++ compile error with template when using self-defined "bind3rd" function

I want to write a function like "bind1st, bind2nd" to support multifields sort by using stl sort. Can't using std:bind since my g++ version is 3.4.5
It is called like this:
#include <alogritm>
std::sort(begin(), end(), bind3rd(SortCond(), indicate));
My template function is:
#ifndef __INCLUDE_TRIPLE_FUNCTION_H_
#define __INCLUDE_TRIPLE_FUNCTION_H_
#define TRIPLE_ARG(Operation, Type) Operation::Type
// Define the triple_function prototype
template<class Arg1, class Arg2, class Arg3, class Result>
struct triple_function
{
// Define the argument type alias
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Arg3 third_argument_type;
typedef Result result_type;
};
template <class Operation>
class binder3rd : public binary_function<typename TRIPLE_ARG(Operation, first_argument_type),
typename TRIPLE_ARG(Operation, second_argument_type), typename TRIPLE_ARG(Operation, result_type)>
{
protected:
Operation m_op;
typename Operation::third_argument_type value;
public:
binder3rd(const Operation& x, const typename Operation::third_argument_type y):m_op(x), value(y){}
// Convert this function to binary_function using the third argment
typename Operation::result_type operator()(const typename Operation::first_argument_type& x, const typename Operation::second_argument_type& y) const
{
return m_op(x, y, value);
}
};
// bind3rd function implementation
template<class Operation, class Arg>
inline binder3rd<Operation> bind3rd(const Operation& fn, const Arg& x)
{
return binder3rd<Operation>(fn, x);
}
#endif //__INCLUDE/TRIPLE_FUNCTION_H_
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
And My test cpp file is:
#include <algorithm>
#include <cstdlib>
#include "triple_function.h"
using namespace std;
class TestClass{
public:
int arr[16];
TestClass() {
for (int i = 0; i < 16; ++i) {
arr[i] = rand() % 100;
}
}
};
// sort by which fields
class Indicate {
public:
int ind[16];
};
struct SortA : public triple_function < TestClass, TestClass, const Indicate, bool >
{
bool operator () (const TestClass& a, const TestClass& b,
const Indicate& indicate) const
{
for (int i = 0; i < 16; ++i) {
int pos = indicate.ind[i];
if (a.arr[pos] == b.arr[pos]) {
continue ;
}
return a.arr[pos] < b.arr[pos];
}
return false;
}
};
int main() {
TestClass a[10];
Indicate ind;
for(int i = 0; i < 16; ++i) {
ind.ind[i] = i;
}
sort(a, a+10, bind3rd(SortA(), ind));
// bind3rd(SortA, ind);
}
when using g++ to compile, I got these compile error:
What's wrong with my code?
In file included from test.cpp:19:
triple_function.h:32: error: expected template-name before '<' token
triple_function.h:32: error: expected `{' before '<' token
triple_function.h:32: error: expected unqualified-id before '<' token
test.cpp: In function `int main()':
test.cpp:62: error: invalid use of undefined type `class binder3rd<SortA>'
triple_function.h:32: error: declaration of `class binder3rd<SortA>'
triple_function.h: In function `binder3rd<Operation> bind3rd(const Operation&, const Arg&) [with Operation = SortA, Arg = Indicate]':
test.cpp:62: instantiated from here
triple_function.h:52: error: return type `class binder3rd<SortA>' is incomplete
triple_function.h:53: error: invalid use of undefined type `class binder3rd<SortA>'
triple_function.h:32: error: declaration of `class binder3rd<SortA>'
The compiler is tripping over your binary_function base class. If you mean std::binary_function, then #include <functional> and the std:: prefix. Of course, since you're not actually defining a binary function, I'm not sure the base class is actually appropriate...
As others have said, std::bind is a better solution to this problem if you can use C++11.
Using std::bind instead, you could do e.g. like this:
#include <functional>
...
bool my_compare(const TestClass& a, const TestClass& b,
const Indicate& indicate)
{
...
}
int main()
{
...
using namespace std::placeholders;
std::sort(a, a+10, std::bind(my_compare, _1, _2, ind));
}