call of overloaded 'swap(char&, char&)' is ambiguous - c++

I can't figure out what is ambiguous about swap(arr[i++],arr[n--]); below. Please educate me on my wrongful ways.
#include <iostream>
#include <string>
template <typename T> void swap ( T & a, T & b )
{
T temp = b;
b = a;
a = temp;
}
template <typename T> void reverse_array ( T * arr, size_t n )
{
size_t i = 0;
while (i < n) swap(arr[i++],arr[n--]); // problem line
}
int main ()
{
char mystr [] = "Obama smokes";
reverse_array(mystr, sizeof(mystr)/sizeof(char));
return 0;
}

codepad has an implicit using namespace std;, which is a really bad idea and makes your swap conflict with std::swap. You can use ::swap instead, but not before fixing your bounds problem by passing sizeof mystr - 2 instead of sizeof(mystr)/sizeof(char).

As #minitech mentions in his answer, the problem is because of the implicit namespace declaration, e.g. using namespace std;
With that I get the following error, which shows that the conflict is with std::swap:
100%] Building CXX object CMakeFiles/csi_projects.dir/main.cpp.o
/home/vsnyc/ClionProjects/main.cpp: In instantiation of ‘void reverse_array(T*, size_t) [with T = char; size_t = long unsigned int]’:
/home/vsnyc/ClionProjects/main.cpp:151:52: required from here
/home/vsnyc/ClionProjects/main.cpp:144:43: error: call of overloaded ‘swap(char&, char&)’ is ambiguous
while (i < n) { swap(arr[i++],arr[n--]); } // problem line
^
/home/vsnyc/ClionProjects/main.cpp:144:43: note: candidates are:
/home/vsnyc/ClionProjects/main.cpp:134:28: note: void swap(T&, T&) [with T = char]
template <typename T> void swap ( T & a, T & b )
^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from /home/vsnyc/ClionProjects/main.cpp:1:
/usr/include/c++/4.8/bits/move.h:166:5: note: void std::swap(_Tp&, _Tp&) [with _Tp = char]
swap(_Tp& __a, _Tp& __b)
^

Related

overloading error for C++ template function

I am trying to do some practice with function templates as in the following example:
#include <iostream>
using namespace std;
template <class T>
T max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
cout << "max(10, 15) = " << max(10, 15) << endl;
retun 0;
}
But I got the following errors. Could anybody recognize where the problem is?
..\src\main.cpp:59:40: error: call of overloaded 'max(int, int)' is
ambiguous
cout << "max(10, 15) = " << max(10, 15) << endl;
^
..\src\main.cpp:16:3: note: candidate: 'T max(T, T) [with T = int]'
T max(T a, T b)
^~~
In file included from c:\mingw\include\c++\8.1.0\bits\char_traits.h:39,
from c:\mingw\include\c++\8.1.0\ios:40,
from c:\mingw\include\c++\8.1.0\ostream:38,
from c:\mingw\include\c++\8.1.0\iostream:39,
from ..\src\main.cpp:9:
c:\mingw\include\c++\8.1.0\bits\stl_algobase.h:219:5: note:
candidate: 'constexpr const _Tp& std::max(const _Tp&, const _Tp&)
[with _Tp = int]'
max(const _Tp& __a, const _Tp& __b)
I am sorry I am new to templates. Thanks for your help.
Your usage of templates is correct, but the compiler complains that there already is a function called max with same arguments.
It's full name would be std::max, but because you wrote using namespace std its just max and compiler cannot know which function to call.
Solution is not to use using, see Why is "using namespace std" considered bad practice? .
using namespace std; is the issue
Please stop using that, see why
The iostream header includes another header file that pulls std::max, giving a compiler error.

nlohmann json ambiguous overload for 'operator='

I'm getting this compilation error with the following code
#include <iostream>
#include <boost/optional.hpp>
#include "nlohmann_json.hpp"
namespace nlohmann {
template <typename T>
struct adl_serializer<boost::optional<T>> {
static void to_json(json& j, const boost::optional<T>& opt) {
if (opt == boost::none) j = nullptr;
else j = *opt;
}
static void from_json(const json& j, boost::optional<T>& opt) {
if (j.is_null()) opt = boost::none;
else opt = j.get<T>();
}
};
}
int main(int argc, char* argv[]) {
nlohmann::json json;
boost::optional<std::string> str = json["str"]; // works
// boost::optional<std::string> str;
// str = json["str"]; // doesn't work
}
The full error message is
nlohmann.cc: In function 'int main(int, char**)':
nlohmann.cc:24:19: error: ambiguous overload for 'operator=' (operand types are 'boost::optional<std::__cxx11::basic_string<char> >' and 'nlohmann::basic_json<>::value_type {aka nlohmann::basic_json<>}')
str = json["str"];
^
In file included from /opt/gcc-7.2.0/include/boost/optional.hpp:15:0,
from nlohmann.cc:2:
/opt/gcc-7.2.0/include/boost/optional/optional.hpp:1019:15: note: candidate: boost::optional<T>& boost::optional<T>::operator=(const boost::optional<T>&) [with T = std::__cxx11::basic_string<char>]
optional& operator= ( optional const& rhs ) = default;
^~~~~~~~
/opt/gcc-7.2.0/include/boost/optional/optional.hpp:1031:15: note: candidate: boost::optional<T>& boost::optional<T>::operator=(boost::optional<T>&&) [with T = std::__cxx11::basic_string<char>]
optional& operator= ( optional && ) = default;
^~~~~~~~
/opt/gcc-7.2.0/include/boost/optional/optional.hpp:1078:15: note: candidate: boost::optional<T>& boost::optional<T>::operator=(boost::none_t) [with T = std::__cxx11::basic_string<char>]
optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
What is the difference between the two assignment operator use cases? Why does the second one not work?
I'm using GCC 7.2.0, with -std=c++14.

Use of funcName() before deduction of auto — why in one case but not the other?

Consider the following code:
#include <unordered_map>
#include <tuple>
namespace Test
{
template<typename State>
struct StateTableEntry
{
State state;
};
template<typename State>
using StateRow = std::unordered_map<int,StateTableEntry<State>>;
template<typename StateRowValueType>
auto& entryBAD(StateRowValueType& row)
{ return row.second; }
template<typename StateRowValueType>
auto entryOK(StateRowValueType& row) -> decltype((row.second))
{ return row.second; }
}
template<class T,int I,class O> std::enable_if_t<I==std::tuple_size<T>::value>
for_each_index_of(O&){}
template<class Tuple, int startingIndex=0, class Operation>
std::enable_if_t<startingIndex<std::tuple_size<Tuple>::value>
for_each_index_of(const Operation& operation)
{
operation(std::integral_constant<std::size_t,startingIndex>());
for_each_index_of<Tuple,startingIndex+1>(operation);
}
int main()
{
for_each_index_of<std::tuple<int>>([](const auto&)
{
Test::StateRow<long> stateRow;
for(auto& rowElement : stateRow)
{
auto& state(entryBAD(rowElement).state);
state=1;
}
});
}
If I try to compile it as is, gcc tells me
test.cpp: In instantiation of ‘main()::<lambda(const auto:1&)> [with auto:1 = std::integral_constant<long unsigned int, 0ul>]’:
test.cpp:29:14: required from ‘std::enable_if_t<(startingIndex < std::tuple_size<_Tp>::value)> for_each_index_of(const Operation&) [with Tuple = std::tuple<int>; int startingIndex = 0; Operation = main()::<lambda(const auto:1&)>; std::enable_if_t<(startingIndex < std::tuple_size<_Tp>::value)> = void]’
test.cpp:43:6: required from here
test.cpp:40:44: error: use of ‘template<class StateRowValueType> auto& Test::entryBAD(StateRowValueType&)’ before deduction of ‘auto’
auto& state(entryBAD(rowElement).state);
^
test.cpp:40:44: error: use of ‘auto& Test::entryBAD(StateRowValueType&) [with StateRowValueType = std::pair<const int, Test::StateTableEntry<long int> >]’ before deduction of ‘auto’
test.cpp:24:1: error: ‘std::enable_if_t<(I == std::tuple_size<_Tp>::value)> for_each_index_of(O&) [with T = std::tuple<int>; int I = 1; O = const main()::<lambda(const auto:1&)>; std::enable_if_t<(I == std::tuple_size<_Tp>::value)> = void]’, declared using local type ‘const main()::<lambda(const auto:1&)>’, is used but never defined [-fpermissive]
for_each_index_of(O&){}
^
But if I move the conde of lambda out of the lambda or replace call of entryBAD with entryOK, for some reason compilation succeeds. Same success if I move definition of entryBAD out of namespace Test.
Also, clang++ 3.6 compiles in all cases without complaints.
Is gcc right or is it a bug in it? If gcc is right, then what's wrong with the code?

Custom allocator works with vector but not with deque (wrapped within a queue)

I have written a custom allocator that allocates memory in a shared memory segment.
This line of code compiles (and runs) fine:
shp_arr = new (vecmem) vector<shape *,smallocator <shape*> > ;
But this line of code:
shp_queue = new (queuemem) queue< shape *, deque < shape *, smallocator< shape * > > > ;
gives me a number of errors. Here they are:
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h: In
instantiation of ‘std::_Deque_base<_Tp, _Alloc>::_Map_alloc_type std::_Deque_base<_Tp,
_Alloc>::_M_get_map_allocator() const [with _Tp = shape*; _Alloc = smallocator<shape*>;
std::_Deque_base<_Tp, _Alloc>::_Map_alloc_type = smallocator<shape**>]’:
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:549:9:
required from ‘void std::_Deque_base<_Tp, _Alloc>::_M_deallocate_map(_Tp**, std::size_t) [with _Tp =
shape*; _Alloc = smallocator<shape*>; std::size_t = unsigned int]’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:568:4:
required from ‘std::_Deque_base<_Tp, _Alloc>::~_Deque_base() [with _Tp = shape*; _Alloc =
smallocator<shape*>]’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:781:15:
required from ‘std::deque<_Tp, _Alloc>::deque() [with _Tp = shape*; _Alloc = smallocator<shape*>]’
file.cpp:233:30: required from here
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:529:53: error:
no matching function for call to ‘smallocator<shape**>::smallocator(const _Tp_alloc_type&)’
/usr/local/lib/gcc/i686-pc-cygwin/4.7.3/../../../../include/c++/4.7.3/bits/stl_deque.h:529:53: note:
candidates are:
In file included from file.cpp:20:0:
smallocator.hpp:41:3: note: smallocator<T>::smallocator(const smallocator<T>&) [with T = shape**;
smallocator<T> = smallocator<shape**>]
smallocator.hpp:41:3: note: no known conversion for argument 1 from ‘const _Tp_alloc_type {aka const
smallocator<shape*>}’ to ‘const smallocator<shape**>&’
smallocator.hpp:40:3: note: smallocator<T>::smallocator() [with T = shape**]
smallocator.hpp:40:3: note: candidate expects 0 arguments, 1 provided
The interface to smallocator looks like this:
template <typename T>
class smallocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef smallocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0)
{
...
}
void deallocate(pointer p, size_type n)
{
...
}
smallocator() throw(): std::allocator<T>() { std::cout <<"Hello allocator" <<std::endl;}
smallocator(const smallocator &a) throw(): std::allocator<T>(a) { }
~smallocator() throw() { }
};
Does anyone know what the problem is? Thanks!
You did not provide the following constructor for your smallocator :
template <class U>
smallocator(const smallocator<U>& a) throw();
You need all three :
smallocator() throw();
smallocator(const smallocator& a) throw();
template <class U>
smallocator(const smallocator<U>& a) throw();

ambiguous call in template error

Can anyone tell me the cause of error ?
Error is
C:\web\template1.cpp||In function 'int main()':|
C:\web\template1.cpp|23|error: call of overloaded 'swap(int&, int&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = int]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = int]|
C:\web\template1.cpp|24|error: call of overloaded 'swap(double&, double&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = double]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = double]|
C:\web\template1.cpp|25|error: call of overloaded 'swap(char&, char&)' is ambiguous|
C:\web\template1.cpp|6|note: candidates are: void swap(X&, X&) [with X = char]|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\move.h|76|note: void std::swap(_Tp&, _Tp&) [with _Tp = char]|
||=== Build finished: 3 errors, 0 warnings ===|
#include <iostream>
using namespace std;
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
swap(i,j);
swap(x,y);
swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}
Your swap conflicts with std::swap. Remove using namespace std; above and correct the rest code from std namespace.
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
Also it's worth reading Why is "using namespace std" considered bad practice?
Rename swap() as swap2() or the like. Or, better, never issue using namespace std;.
As written, your code introduces std::swap() through iostream, then dumps it atop your own swap() by using namespace.
There is already a swap function declared somewhere in your code. Change the function's name or remove the declaration of the other swap function.
This ambiguous errors occur due to using std functions as general functions.
There are two ways to overcome this.
1) Instead of declaring using namespace std; use std::cout
whenever you need to print any and std::endl for new line.
#include <iostream>
template <typename X>
void swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
swap(i,j);
swap(x,y);
swap(a,b);
std::cout<<"i="<<i<<"\tj="<<j<<std::endl;
std::cout<<"x="<<x<<"\ty="<<y<<std::endl;
std::cout<<"a="<<a<<"\tb="<<b<<std::endl;
return 0;
}
2) You can also change the swap to Swap to not conflict with the inbuilt std::swap function.
#include <iostream>
using namespace std;
template <typename X>
void Swap(X &a, X &b)
{
X temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
Swap(i,j);
Swap(x,y);
Swap(a,b);
cout<<"i="<<i<<"\tj="<<j<<endl;
cout<<"x="<<x<<"\ty="<<y<<endl;
cout<<"a="<<a<<"\tb="<<b<<endl;
return 0;
}