Позволено ли е претоварване на функция чрез препратка, когато няма неяснота?

Помислете за следния код:

#include <iostream>

void foo(int m);
void foo(int &k);

int main()
{
    foo(5); // ok, because there is no ambiguity

    int m = 5;
    //foo(m); // compile-time error, because of ambiguity
    foo(m + 0); // ok, because it's an expression of type int and not object's lvalue
}

void foo(int m)
{
    std::cout << "by value\n";
}
void foo(int &k)
{
    std::cout << "by reference\n";
}

Разбирам, че въвежда двусмислие за foo(m), но позволено ли е това, когато изразът е от тип int (или друг, който може да се преобразува в int)?

Опитах се да намеря някаква стандартна справка за това, но без успех.


Отказ от отговорност: Имайте предвид, че не е дубликат на Претоварване на функции въз основа на стойност спрямо препратка към константа. Препратките const са различни, тъй като могат да бъдат присвоени с rстойности, за разлика от „обикновените“, не-const препратки.


person Grzegorz Szpetkowski    schedule 16.07.2015    source източник
comment
m също е израз от тип int.   -  person Kerrek SB    schedule 16.07.2015
comment


Отговори (2)


Да, разрешено е.

Няма правило за предотвратяване на това претоварване.

[C++14: 13.1/1]: Не всички декларации на функции могат да бъдат претоварени. Тук са посочени тези, които не могат да бъдат претоварени. [..]

[C++14: 13.1/2]: (бла-бла много изключения, без нито едно за този случай)

Би било изключително ограничаващо за езика да забранява претоварването на функции, което може да бъде двусмислено в определени сценарии с определени извиквания и без основателна причина, бих могъл да добавя!

person Lightness Races in Orbit    schedule 16.07.2015

13.1 [over.load] е доста ясно (с изключение на бележка от много страници) за това кои функции не могат да бъдат претоварени в същия обхват.

Вашият случай не е посочен там и можете да декларирате тези претоварвания, просто не можете непременно да ги използвате лесно. Можете да наречете lvalue така:

void (*f)(int&) = foo;
f(m);

Това избягва двусмислието, което се случва, когато извиквате foo(m).

Освен това: друг начин за запис на foo(m + 0) е просто foo(+m), унарният оператор + преобразува lvalue в rvalue, така че се извиква претоварването foo(int).

person Jonathan Wakely    schedule 16.07.2015