Make int overload a preferable one

Viewed 97

Consider following code snippet:

class Foo {
public:
    void bar(std::size_t){}
    void bar(const char* ){}
};

int main() {
    auto foo = Foo{};
    foo.bar(0);
}

It produces ambiguous calls errors (check here). But I think from programmer's perspective it is pretty obvious that I want to call overload with std::size_t. My question is if anything can be done so this code does not produce errors and calls size_t overload?

4 Answers

can be done like this in C++ 20

#include <cstdint>
#include <iostream>
#include <type_traits>
class Foo {
public:
    template <typename T>
    requires std::is_integral_v<T>
    void bar(T){
        std::cout<<"hello size_T";
    }
    
    
    void bar(const char* ){
        std::cout<<"hello";
    }
};

int main() {
    auto foo = Foo{};
    foo.bar(25);
}

In modern c++ (at least c++17), we prefer to pass string_view as argument over const char* for the none owner transfer cases, so a considerable choice:

#include <cctype>
#include <string>
class Foo {
public:
    void bar(std::size_t){}
    void bar(std::string_view){}
};

int main() {
    auto foo = Foo{};
    foo.bar(0);
}

Online demo

In below C++ 20, this works well.

#include <iostream>

class Foo {
public:
    template <typename T>   
    void bar(T) {
        std::cout << "hello T" << std::endl;
    }

    void bar(const char* c) {
        std::cout << c << std::endl;
    }
};

int main() {
    auto foo = Foo{};
    foo.bar(0);
    foo.bar("test.");
}

This works in C++23:

foo.bar(0zu);

and this works pre-C++23:

foo.bar(size_t{0});
Related