initialisation of iterator with a reference - c++11

in C++11: I want to create an iterator from a reference. this is to make a loop starting from a given position rather than from begin().
I tried:
typename std::vector<T>::iterator ref2iter(T& x)
{
return &x ;
} ;
but was answered:
conversion from ‘double*’ to non-scalar type ‘std::vector<double, std::allocator<double> >::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >}’ requested

Related

CGAL coordinate value transformation not working anymore in 5.2.1

In a project of mine I used to transform coordinate values from Kernel::FT to CGAL::Gmpq and back. The code does not compile anymore with the same kernel choice as before, namely
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
But with the alternative I tried without being sure of it being completely equivalent to the former one everything compiled without errors:
typedef CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > Kernel;
My header definitions
// the following kernel gives no error
//typedef CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > Kernel;
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Circle_2 Circle_2;
typedef Kernel::Line_2 Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2;
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_2;
typedef Traits_2::Curve_2 Curve_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef Traits_2::Point_2 Point_2t;
typedef Traits_2::CoordNT coordnt;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
The code that fails
CGAL::Gmpfr convert(CGAL::Gmpq z)
{
CGAL::Gmpz num = z.numerator();
CGAL::Gmpz den = z.denominator();
CGAL::Gmpfr num_f(num);
CGAL::Gmpfr den_f(den);
return num_f/den_f;
}
CGAL::Gmpfr convert(Traits_2::CoordNT z, int use_precision)
{
Kernel::FT a0_val = z.a0();
Kernel::FT a1_val = z.a1();
Kernel::FT root_val = z.root();
//the following three lines give errors
CGAL::Gmpq a0_q = a0_val.exact();
CGAL::Gmpq a1_q = a1_val.exact();
CGAL::Gmpq root_q = root_val.exact();
CGAL::Gmpfr a0_f = convert(a0_q);
CGAL::Gmpfr a1_f = convert(a1_q);
CGAL::Gmpfr root_f = convert(root_q);
CGAL::Gmpfr res = a0_f + a1_f * root_f.sqrt(use_precision);
return res;
}
Point_2 convert(Point_2t p)
{
CGAL::Gmpfr xx = convert(p.x());
CGAL::Gmpfr yy = convert(p.y());
CGAL::Gmpq xx1 = xx;
CGAL::Gmpq yy1 = yy;
// the following two lines give errors
Kernel::FT xx2 = xx1;
Kernel::FT yy2 = yy1;
Point_2 pp(xx2, yy2);
return pp;
}
The errors (the first three and the last two are essential identical):
cgal.cpp:48:32: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq a0_q = a0_val.exact();
~~~~~~~~~~~~^~
cgal.cpp:49:32: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq a1_q = a1_val.exact();
~~~~~~~~~~~~^~
cgal.cpp:50:36: error: conversion from ‘CGAL::Lazy<CGAL::Interval_nt<false>, boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>, CGAL::To_interval<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> > >::ET {aka boost::multiprecision::number<boost::multiprecision::backends::gmp_rational>}’ to non-scalar type ‘CGAL::Gmpq’ requested
CGAL::Gmpq root_q = root_val.exact();
~~~~~~~~~~~~~~^~
cgal.cpp: In function ‘Point_2 convert(Point_2t)’:
cgal.cpp:71:19: error: conversion from ‘CGAL::Gmpq’ to non-scalar type ‘CGAL::Lazy_kernel_generic_base<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> >, CGAL::Cartesian_converter<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> > >, CGAL::Epeck>::FT {aka CGAL::Lazy_exact_nt<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >}’ requested
Kernel::FT xx2 = xx1;
^~~
cgal.cpp:72:19: error: conversion from ‘CGAL::Gmpq’ to non-scalar type ‘CGAL::Lazy_kernel_generic_base<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> >, CGAL::Cartesian_converter<CGAL::Simple_cartesian<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >, CGAL::Simple_cartesian<CGAL::Interval_nt<false> > >, CGAL::Epeck>::FT {aka CGAL::Lazy_exact_nt<boost::multiprecision::number<boost::multiprecision::backends::gmp_rational> >}’ requested
Kernel::FT yy2 = yy1;
It seems that the default kernel CGAL::Exact_predicates_exact_constructions_kernel now has a coordinate number type related to "boost-something" and this is not compatible to CGAL::Gmpq anymore.
What is the best solution to the problem, given that I want to use the fastest kernel equivalent to a CGAL::Exact_predicates_exact_constructions_kernel?
Shall I switch to CGAL::Cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> > or even to CGAL::Extended_cartesian< CGAL::Lazy_exact_nt<CGAL::Gmpq> >?
Or can I set a certain environment variable so that CGAL::Exact_predicates_exact_construction_kernel works with CGAL::Gmpq by default instead of "boost-something", provided this does not make things slower?
Or can I just rewrite the offending lines with some newly introduced conversion operators/functions in CGAL 5.2.1. I am at the moment not aware of?
If you look at CGAL/Exact_predicates_exact_constructions_kernel.h to see how Epeck is defined, you can define you own version of Epeck using Gmpq as
class Kernel
: public Type_equality_wrapper<
Lazy_kernel_base< Simple_cartesian<Gmpq>,
Simple_cartesian<Interval_nt_advanced>,
Cartesian_converter< Simple_cartesian<Gmpq>,
Simple_cartesian<Interval_nt_advanced> >,
Kernel>,
Kernel >
{};
(you may need to add CGAL:: all over)
The rational type chosen by default depends on what is available, it can come from boost.Multiprecision (you can disable that choice with CGAL_DO_NOT_USE_BOOST_MP). It can come from GMPXX if CGAL_USE_GMPXX is defined. It can also be Gmpq (CGAL_USE_GMP but not CGAL_USE_GMPXX), leda_rational, etc.
I understand this variability may not be ideal for not-so-usual cases like yours where you care about the type...
I have never used Gmpfr, but it should not be hard to add constructors from mpz_class and mpz_int similar to the one from Gmpz (do you want to file an enhancement request on github, or possibly write it yourself? It may be a 1-liner, not counting the #ifdef). And then it would likely be possible to write your convertor in a way that is at least portable to all the GMP-based rationals, maybe using Fraction_traits<FT>::Decompose, although that will do an unnecessary copy. Actually, it may even make sense to add constructors to Gmpfr from rational types directly using mpfr_set_q.

C2664 cannot convert to && value

The compiler wants my lvalue to be a rvalue reference and I dont see why.
My questions are:
Why is "dataLen" const, even though it was declared non const and the lambda is told to catch by reference as default?
Why does the compiler try to convert to rvalue reference "unsigned __int64 &&", even though it was declared "unsigned long long" (no rvalue reference) for tupleByteVector_content?
I think it is because of the lambda capture, but please see this simplified workflow below:
void read_socket()
{
std::vector<std::tuple<unsigned long long, std::vector<unsigned char>>> tupleByteVector_content;
read_socket_readSome(tupleByteVector_content, [this, &tupleByteVector_content]() {
//use tuple vector
});
}
//catch the tuple vector by reference
void read_socket_readSome(std::vector<std::tuple<unsigned long long, const std::shared_ptr<Session>& session, std::vector<unsigned char>>> & tupleByteVector_content, std::function<void()> && continueReadFunction)
{
//Read data length from a asio socket
std::shared_ptr<asio::streambuf> len_buffer = std::make_shared<asio::streambuf>();
asio::async_read(session->connection->socket->next_layer(), *len_buffer, asio::transfer_exactly(1), [&,
this, session, len_buffer, tupleByteVector_content, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {
//the first value I want to save
unsigned long long dataLen = BytesToLength(len_buffer);
//Read data from a asio socket
std::shared_ptr<asio::streambuf> data_buffer = std::make_shared<asio::streambuf>();
asio::async_read(session->connection->socket->next_layer(), *data_buffer, asio::transfer_exactly(dataLen), [&, this, dataLen, data_buffer, tupleByteVector_content, session, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {
//ERROR HERE: ----------->
std::tuple<unsigned long long, std::vector<unsigned char>> t =
std::make_tuple<unsigned long long, std::vector<unsigned char>>(
dataLen, // ERROR C2664, cant convert argument 1 from "const unsigned __int64" to "unsigned __int64 &&"
{ asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) });
//ERROR HERE: <-----------
tupleByteVector_content.push_back(t);
continueReadFunction();
});
});
}
EDIT:
I was able to compile this tuple:
std::tuple<unsigned long long, std::vector<unsigned char>> t = { dataLen, { asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) } };
But then the push_back to the vector gives the error:
error C2663: [...] ::push_back": for 2 overloads there is no conversion for the this-pointer (free translation into english from myself)
dataLen is treated as const because you capture it by value:
[&, this, dataLen,
^^^
By default function call operator generated for closure is marked as const, so inside const method you can only read data. Modifications are not allowed, unless you add mutable to definition of lambda.
When you use make_tuple you should rely on template argument deduction instead putting types in explicit way, as you did it. Short version of your issue:
int i;
std::tuple<int> t = std::make_tuple<int>(i);
i is named object, so it is lvalue. By make_tuple<int> you make make_tuple signature look like: make_tuple(int&&). This is the place where compiler complains, because i as lvalue cannot be bound to rvalue reference. With argument deduction, parameter of make_tuple is deduced to be: int&, and in this case i can be bound.
push_back on vector doesn't work, because again you captured vector by value. push_back modifies object, which is not allowed when calling on const object. You should capture it by reference.

C++ unordered_map move beginner error

Sorry for the noob question here, but i don't even know what to search on google. I tried some documention on the move semantic but i still can't solve my problem.
So if somebody can give me some clues, i'll be really thanksfull.
About the code:
graph.hpp:
#ifndef GRAPH_HPP
#define GRAPH_HPP
#include <cstdlib>
#include <unordered_map>
#include <vector>
#include <string>
template<typename T, typename U>
class Link;
template<typename T, typename U>
class Node;
namespace graph
{
template<typename T, typename U>
class Link
{
public:
Link() = default;
Link(U&& data, T& node) : _data(data), _endNode(node) {}
~Link() = default;
private:
U _data;
Node<T, U>& _endNode;
};
template<typename T, typename U>
class Node
{
public:
Node() = default;
Node(T&& data) : _data(data) {};
~Node() = default;
private:
T _data;
std::vector<Link<T, U>> _links;
};
template<typename K, typename T, typename U>
class Graph
{
public:
Graph() = default;
~Graph() = default;
private:
size_t _nbNode;
std::unordered_map<K, Node<T, U>> _nodes;
public:
#include "graph.tpp"
};
}
#endif
graph.tpp:
void add_Link(const K& key1,
const K& key2,
U&& linkInfo)
{
if (!_nodes.count(key1)
|| !_nodes.count(key2))
throw "Key doesn't exist!";
Link<T, U> newLink(linkInfo, _nodes[key2]);
_nodes[key1].links.push_back(newLink);
}
void add_Node(K& key, T&& elem)
{
Node<T, U> newNode(std::move(elem));
_nodes[key] = std::move(newNode);
}
main.cpp:
#include "graph.hpp"
#include <string>
int main()
{
std::string name("name");
graph::Graph<std::string, std::string, std::string> graph;
graph.add_Node(name, "lol");
return 0;
}
I just want to add a new element in the unordered_map with a move. But it's just say me :
clang++ -Wall -Wextra -std=c++14 -O2 -march=native -s -fomit-frame-pointer -c src/test.cpp -o obj/test.o -I ./src/include -I ./src/template/
clang: warning: argument unused during compilation: '-s'
In file included from src/test.cpp:1:
In file included from ./src/include/graph.hpp:15:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy
assignment operator is implicitly deleted
*__result = *__first;
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false,
std::random_access_iterator_tag>::__copy_m<const graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
_Category>::__copy_m(__first, __last, __result);
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, const graph::Link<std::basic_string<char>,
std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first),
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<const
graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >,
__gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>,
std::basic_string<char> > > > > >' requested here
return (std::__copy_move_a2<__is_move_iterator<_II>::__value>
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:206:27: note: in instantiation of function template specialization 'std::copy<__gnu_cxx::__normal_iterator<const
graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >,
__gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>,
std::basic_string<char> > > > > >' requested here
std::_Destroy(std::copy(__x.begin(), __x.end(), begin()),
^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > >
>::operator=' requested here
class Node
^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here
graph.add_Node(name, "lol");
^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type
'Node<std::basic_string<char>, std::basic_string<char> > &'
Node<T, U>& _endNode;
^
In file included from src/test.cpp:1:
In file included from ./src/include/graph.hpp:15:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy
assignment operator is implicitly deleted
*__result = *__first;
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false,
std::random_access_iterator_tag>::__copy_m<graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
_Category>::__copy_m(__first, __last, __result);
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, graph::Link<std::basic_string<char>,
std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first),
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, graph::Link<std::basic_string<char>,
std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
return (std::__copy_move_a2<__is_move_iterator<_II>::__value>
^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:211:13: note: in instantiation of function template specialization 'std::copy<graph::Link<std::basic_string<char>, std::basic_string<char> >
*, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(),
^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > >
>::operator=' requested here
class Node
^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here
graph.add_Node(name, "lol");
^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type
'Node<std::basic_string<char>, std::basic_string<char> > &'
Node<T, U>& _endNode;
^
2 errors generated.
Makefile:43: recipe for target 'obj/test.o' failed
make: *** [obj/test.o] Error 1
Sorry for the trouble, have a nice day.
Okay. The problem is in this line:
_nodes[key] = std::move(newNode);
You are trying to move-assign Node<T, U>. However, Node will not have a move assignment operator implicitly declared as defaulted because there is a user-declared destructor:
~Node() = default;
As a result, that line actually calls the copy assignment operator of Node<T, U>, which performs a member-wise copy. One of the members of Node<T, U> is of type std::vector<Link<T, U>>, where Link<T, U> has a member variable that is a reference. References aren't copy-assignable, so the copy assignment operator is implicitly deleted. Hence, there is no copy assignment operator found, so the line is ill-formed.
While references aren't move-assignable either, a vector<Link<T,U>> is move-assignable, so the simplest solution is to just delete the line where you declare the destructor as defaulted:
//~Node() = default;
With that, the compiler will implicitly declare the default move constructor/assignment, and this code will do what you expect. And compile.
Side-note, this is a really bad idea:
public:
#include "graph.tpp"
};

C++11 rvalue reference and const-ness

The following code is a snippet of a tuple-like class where it is possible to get a reference to a given type in the tuple, or if that type is not found, the provided default value will be returned instead.
If the default value is a lvalue a reference must be returned, if the default value is a rvalue then a rvalue must be returned.
The following code illustrates the problem I'm having:
struct Foo {
Foo(int d) : data(d) {}
template <typename T, typename TT>
const TT get_or_default(TT&& t) const {
return data;
}
template <typename T, typename TT>
TT get_or_default(TT&& t) {
return data;
}
int data;
};
int main(int argc, char* argv[]) {
int i = 6;
const Foo foo1(5);
Foo foo2(5);
// compile error
foo1.get_or_default<int>(i);
// works
foo1.get_or_default<int>(5);
foo2.get_or_default<int>(i) = 4;
foo2.get_or_default<char>('a');
return 0;
}
When compiling this I get the following error:
cxx.cxx:6:20: error: binding of reference to type 'int' to a value of type 'const int' drops qualifiers
return data;
^~~~
cxx.cxx:23:14: note: in instantiation of function template specialization 'Foo::get_or_default<int, int &>' requested here
foo1.get_or_default<int>(i);
^
1 error generated.
There is a special rule for template argument deduction when the function parameter is of type T&& where T is a template parameter. That rule is:
If the function argument is an lvalue of type U, then U& is used in place of U for type deduction in this case.
It's used to allow perfect forwarding. Basically, it means that T&& for a template parameter T is a "universal reference."
In your case, since i is indeed an lvalue, TT is deduced to int&. Applying a const to that is ignored (it would apply to the reference itself, not to the type referred to), so the fucntion instantiated from the template looks something like this:
int& get_or_default(int& t) const {
return data;
}
And since the function is const, data is considered const as well and so it cannot bind to a non-const reference.

Type of iterator for range-based for loop

Say I have the following code:
std::vector<std::string> foo({"alice", "bob"});
for (const std::string &f : foo)
std::cout << f.size() << std::endl;
if I make a mistake and change f.size() to f->size(), I get the following error from GCC:
error: base operand of ‘->’ has non-pointer type ‘const string {aka
const std::basic_string}
Why is the actual type const std::basic_string<char> rather than const std::basic_string<char> & (reference)?
The left-hand side of -> operator is an expression. There ain't no such thing as an expression with a reference type:
5p5 If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.

Resources