Using (templated) overloaded functions to prevent common arithmetic conversions

I often find that I want to prevent narrowing or signature of conversions (and in general Normal arithmetic conversions ) for specific constructors or functions, I prefer to write:

#include <iostream>

void foo(double f){
    std::cout << "foo double" << f <<std::endl;
}
void foo(float) = delete;
// or template<typename T> void foo(T&& f) = delete;

void bar(unsigned int f){
    std::cout << "bar uint " << f <<std::endl;
}
void bar(signed int ) = delete;
// or template<typename T> void bar(T&& f) = delete;

It does the job ...

int main() {
    auto i=2;
    auto d=2.0;
    auto f=2.0f;
    foo(i); // prevented
    foo(d); // OK
    foo(f); // prevented

    auto uil = 3ull;
    auto ul = 3ul;
    auto u = 3u;
    bar(i); // prevented
    bar(d); // prevented
    bar(f); // prevented
    bar(uil); // prevented
    bar(ul); // prevented
    bar(u); // OK
}

Now, is it just a matter of taste in these cases, if I use a remote template or a remote function without a template, or are there cases where it matters? I found that the remote template is more explicit, in preventing all T, but, on the other hand, when using this template with constructors; shipment constructors have their problems . In the case of the template version, would it be better to make a remote template const T&instead?

+4
1

-, , , , , , , . - , , , " ", " , , ?". .

, -.

- - foo({f});, , , , .

foo({i});, foo({3}); (3 , double , 3 double ). , .

:

enum E : unsigned { };

int main() 
{
    E e{};
    bar(e);
}

, . , E to unsigned int , , E - int, .

, , , short , int, char16_t, char32_t wchar_t, .

, , , :

struct A
{
   operator double() { return 7.0; }
};

int main() 
{
   A a{};
   foo(a);
}

, , , - ( foo(double)).

+3

Source: https://habr.com/ru/post/1667747/


All Articles