Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

code doesn't compile with a specific name function

Tags:

c++

g++

This piece of code doesn't compile on my computer (EDIT with minimal example):

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <tuple>

template<class PValues>
inline bool equal(PValues it,
                  PValues last,
                  size_t  cols,
                  size_t  rows,

                  size_t offset)
{
  if(std::distance(it,last)<offset)
    return false;

  for(size_t c=0; c<cols; ++c)
    {
      auto p = it + c*rows;
      if(*p != *(p + offset))
        return false;
    }

  return true;
};



int main()
{
  std::vector<std::string> vec = {"1","1","1","2","2","2","3","8","8",
                                  "5","5","2","5","5","5","6","8","8",
                                  "3","3","3","4","4","3","9","8","8"};
  std::vector<double> nbs = {1,2,3,4,5,6,7,8,9};

  auto res = equal(vec.data(), vec.data()+9, 3, 9, 1);
}

I have the following error :

In file included from /usr/include/c++/9/bits/char_traits.h:39,
                 from /usr/include/c++/9/ios:40,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from main.cpp:2:
/usr/include/c++/9/bits/stl_algobase.h: In instantiation of ‘bool std::__equal4(_II1, _II1, _II2, _II2, _BinaryPredicate) [with _II1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _II2 = long unsigned int; _BinaryPredicate = int]’:
/usr/include/c++/9/bits/stl_algobase.h:1219:38:   required from ‘bool std::equal(_IIter1, _IIter1, _IIter2, _IIter2, _BinaryPredicate) [with _IIter1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _IIter2 = long unsigned int; _BinaryPredicate = int]’
main.cpp:60:15:   required from ‘size_t remove_duplicates_rows_impl(PValues, PResults, size_t, size_t) [with PValues = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; PResults = __gnu_cxx::__normal_iterator<double*, std::vector<double> >; size_t = long unsigned int]’
main.cpp:99:32:   required from here
/usr/include/c++/9/bits/stl_algobase.h:1139:13: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<long unsigned int>’
 1139 |       using _Cat2 = typename iterator_traits<_II2>::iterator_category;
      |             ^~~~~
/usr/include/c++/9/bits/stl_algobase.h:1140:13: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<long unsigned int>’
 1140 |       using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>;
      |             ^~~~~~~~
/usr/include/c++/9/bits/stl_algobase.h:1144:29: error: no matching function for call to ‘distance(long unsigned int&, long unsigned int&)’
 1144 |    auto __d2 = std::distance(__first2, __last2);
      |                ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:66,
                 from /usr/include/c++/9/bits/char_traits.h:39,
                 from /usr/include/c++/9/ios:40,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from main.cpp:2:
/usr/include/c++/9/bits/stl_iterator_base_funcs.h:138:5: note: candidate: ‘template<class _InputIterator> constexpr typename std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator, _InputIterator)’
  138 |     distance(_InputIterator __first, _InputIterator __last)
      |     ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator_base_funcs.h:138:5: note:   template argument deduction/substitution failed:
/usr/include/c++/9/bits/stl_iterator_base_funcs.h: In substitution of ‘template<class _InputIterator> constexpr typename std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator, _InputIterator) [with _InputIterator = long unsigned int]’:
/usr/include/c++/9/bits/stl_algobase.h:1144:29:   required from ‘bool std::__equal4(_II1, _II1, _II2, _II2, _BinaryPredicate) [with _II1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _II2 = long unsigned int; _BinaryPredicate = int]’
/usr/include/c++/9/bits/stl_algobase.h:1219:38:   required from ‘bool std::equal(_IIter1, _IIter1, _IIter2, _IIter2, _BinaryPredicate) [with _IIter1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _IIter2 = long unsigned int; _BinaryPredicate = int]’
main.cpp:60:15:   required from ‘size_t remove_duplicates_rows_impl(PValues, PResults, size_t, size_t) [with PValues = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; PResults = __gnu_cxx::__normal_iterator<double*, std::vector<double> >; size_t = long unsigned int]’
main.cpp:99:32:   required from here
/usr/include/c++/9/bits/stl_iterator_base_funcs.h:138:5: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<long unsigned int>’
In file included from /usr/include/c++/9/bits/char_traits.h:39,
                 from /usr/include/c++/9/ios:40,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from main.cpp:2:
/usr/include/c++/9/bits/stl_algobase.h: In instantiation of ‘bool std::__equal4(_II1, _II1, _II2, _II2, _BinaryPredicate) [with _II1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _II2 = long unsigned int; _BinaryPredicate = int]’:
/usr/include/c++/9/bits/stl_algobase.h:1219:38:   required from ‘bool std::equal(_IIter1, _IIter1, _IIter2, _IIter2, _BinaryPredicate) [with _IIter1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _IIter2 = long unsigned int; _BinaryPredicate = int]’
main.cpp:60:15:   required from ‘size_t remove_duplicates_rows_impl(PValues, PResults, size_t, size_t) [with PValues = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; PResults = __gnu_cxx::__normal_iterator<double*, std::vector<double> >; size_t = long unsigned int]’
main.cpp:99:32:   required from here
/usr/include/c++/9/bits/stl_algobase.h:1153:37: error: invalid type argument of unary ‘*’ (have ‘long unsigned int’)
 1153 |  if (!bool(__binary_pred(*__first1, *__first2)))
      |                                     ^~~~~~~~~
/usr/include/c++/9/bits/stl_algobase.h:1153:25: error: ‘__binary_pred’ cannot be used as a function
 1153 |  if (!bool(__binary_pred(*__first1, *__first2)))

What seems strange to me is : if I change the name of the function equal to equalx (or equalz, just an example), it compiles. The code doesn't compile on godbolt to, but it compiles on onlinegdb : https://onlinegdb.com/ryM5LK4JP .

My version of g++ :

g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

Line use to compile the example :

g++ -std=c++17 -o main main.cpp

like image 652
Kafka Avatar asked Jul 09 '20 12:07

Kafka


1 Answers

If you change the call to equal from equal(first_v, last_v, cols, rows, 1) to
equal(first_v, last_v, cols, rows, size_t(1)), the code compiles.

The reason the code compiles if you change the name is that there's a standard algorithm named std::equal. This function is looked at in overload resolution because the first two arguments share the std namespace with the function, so argument-dependent lookup happens.
std::equal may take 5 arguments, all of which are templated, so that will be selected as the best match in overload resolution. To use your function, there would have to be an implicit conversion from int to size_t.
By changing the last parameter to size_t(1) there's no conversion necessary to call your function, thus that is what is selected in overload resolution.

like image 186
IlCapitano Avatar answered Nov 06 '22 07:11

IlCapitano