0

I have a code like this:

   set<array<int, 3>> s;
   int ar[3] = {1,2,3};
   s.insert(ar);
   auto it = s.find(ar);

And the message of IDE that no instance of overloaded function insert/find. If I use std::array it is ok, ::insert and ::find work in the same way. But what if i wanna use these C arrays T[N] or find function with std::array in set should return iterator if two of three elements equal. Or set::insert will not insert a new array if it is a permutation of exist, I mean s.insert({1,2,3}) - already added, s.insert({3,2,1}) - return iterator on {1,2,3}.

The question is how to overload STD functions? Not in this code especially but in general? Any link or real code example welcome. May be its a really simple question for experienced programmers) but there are a lot of examples of operator overloading, but no for STL. Thanks.

SternK
  • 11,649
  • 22
  • 32
  • 46
  • 4
    Why not declare an `array ar{ {1,2,3} }` in your function instead of an `int ar[3]`? – Shloim Dec 25 '19 at 13:10
  • Yeap, it works that way. But i want to understand some things about overloading STL at all. – Alexey Chicherin Dec 25 '19 at 13:26
  • Note that the days of STL are [gone](https://stackoverflow.com/questions/5205491/whats-the-difference-between-stl-and-c-standard-library). It has now become a part of the standard library. – Evg Dec 25 '19 at 13:33
  • We can use the unordered map/set container with specialized version of hashing https://en.cppreference.com/w/cpp/utility/hash – Build Succeeded Dec 25 '19 at 13:36
  • @Evg -- unfortunately, "STL" now stands for STandard Library. – Pete Becker Dec 25 '19 at 14:12
  • @PeteBecker, should "STL" be used to refer to the standard library nowadays? – Evg Dec 25 '19 at 14:16
  • 2
    @Evg -- "should .. be used"? No. "is widely used"? Yes. :-( – Pete Becker Dec 25 '19 at 14:17
  • @Evg it is informative :) Before i`v read this i think STL - always mean STandart Library of C++. All what in namespace std. But it have another value.Full time holy war about this.. But in question i mean standard library. – Alexey Chicherin Dec 25 '19 at 15:09
  • @AlexeyChicherin, BTW, the author of STL is russian-american programmer Alexander Stepanov. :) – Evg Dec 25 '19 at 15:44

4 Answers4

4

You cannot declare additional overloads for a member function of a class outside the class definition. The language does not provide syntax for it. Since you can't modify the class definition in the standard library headers, you cannot add additional overloads to them either.


Free functions in the std namespace may not be overloaded. There is syntax for it (the same way any overloads of free functions work), but doing so causes undefined behavior, because it is explicitly forbidden in the standard, see [namespace.std]/1.


What is usually (exceptions apply) allowed is to define template specializations for entities in the std namespace, but only if the specialization depends on a user-defined type and not for member functions, member function templates or member class templates. See the rest of the quoted and following paragraph linked above.

A common example where specialization inside the std namespace is used is std::hash for use as hash function in unordered associative containers:

struct my_type {
    //...
};

namespace std {
    template<>
    struct hash<my_type> {
        auto operator()(my_type const& x) const noexcept {
            //...
        }
    };
}

But even something like that is not allowed if my_type is replaced by int*, int[3] or std::array<int, 3> or anything similar, because there is no dependence on a user-declared type.


If you want to make a std::array from a built-in array, you will be able to use std::to_array in C++20:

set<array<int, 3>> s;

int ar[3] = {1,2,3};

s.insert(std::to_array(ar));

auto it = s.find(std::to_array(ar));

Before C++20, you might have the function available as std::experimental::to_array in #include<experimental/array> or you can define it yourself (from cppreference.com; requires #include<type_traits>, #include<utility> and #include<cstddef>):

namespace detail {

template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
    to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
    return { {a[I]...} };
}

}

template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
    return detail::to_array_impl(a, std::make_index_sequence<N>{});
}
walnut
  • 21,629
  • 4
  • 23
  • 59
0

About the other question - about permutations, i.e., that you want your set to find iterator to {1,2,3} when you look for a permutation of it.

Technically, you can do 2 things:

(1) make a specialized comparison operator for which permutations are equivalent. Or make a class that wraps std::array and implement its comparison operators this way.

(2) (preferred) simply sort your array before adding it to set and/or searching for it.

If you need its elements in original order, then I recomend to make utility class that contains both the original array and sorted version that it uses for comparisons.

If you also want to be able to add option for having multiple original while returning the exact one when it exists... then its more complicated. It can be done with some composite functions.

ALX23z
  • 4,456
  • 1
  • 11
  • 18
0

Just like @walnut said, you cannot declare additional overloads for a member function of a class outside the class definition. Other than encapsulate your own int<3> class, there is another work around - operator << override.

set<array<int, 3>>& operator << (set<array<int, 3>>& s, int ar[3])
{
    array<int,3> ar2 { ar[0], ar[1], ar[2] };
    s.insert(ar2);

    return s;
}

It looks weird, but easy to use.

Now you can do this

set<array<int, 3>> s;
int ar[3] = {1,2,3};

s << ar;

However, if there is a bunch of functions you want to use in set against int[3] against array, It is better to define your own class / struct.

template <class T, int arsize>
struct MyFixedArray
{
    T ar[arsize];
    MyFixedArray(T _ar[arsize]) {
        for (int i = 0; i < arsize; ++i)
            ar[i] = _ar[i];
    };
    operator array<T, arsize>() const {
        array<T, arsize> _ar;
        for (int i = 0; i < arsize; ++i)
            _ar[i] = ar[i];

        return _ar;
    };
};

and now you can use it freely everwhere

MyFixedArray<int, 3> myar(ar);

s.insert(myar);
auto it = s.find(myar);
Tony
  • 632
  • 1
  • 4
  • 18
  • I`m trying to compile and it works:) Сould you clarify about the insert operation here? I mean if we using is set, set::insert trying to find existing element, compare by key value, if there is no equal insert new element of set, if equal return iterator. If it set> set::insert overloaded in standard library, and trying to find full equality of each[n] position in array and make the same. But here we pass the value of MyFixedArray class. How this conversion to array happen? If will be two varaible like T ar[arsize] and T ar2[arsize]; Which will be used? – Alexey Chicherin Dec 25 '19 at 17:01
  • operator array() const { … } is the conversion operator override. When you use set>::insert, it is looking for array as a parameter, but you passed in MyFixedArray. It has a conversion operator to array, so it will be called to do the conversion, then pass to insert. – Tony Dec 25 '19 at 18:37
-1

I don't think that C++ gives you the right to do so. For more information, you may get this answer useful in your case. I hope that helps your problem.

Mohammed Deifallah
  • 1,290
  • 1
  • 10
  • 25
  • Thank you. As i understand this : "A program may add a template specialization for any standard library template..." mean that [std::set::find](https://en.cppreference.com/w/cpp/container/set/find) - have template version and i can create specialization?, and [std::set::insert] (https://en.cppreference.com/w/cpp/container/set/insert) - do not have. Of course i can create new container and add in it any features, but without c++ STL perfomance – Alexey Chicherin Dec 25 '19 at 14:08
  • @AlexeyChicherin, you can't. The template version of `.find` is there to support transparent comparators. See [this question](https://stackoverflow.com/questions/20317413/what-are-transparent-comparators). – Evg Dec 25 '19 at 14:29