До C ++ 20 вам нужно указать компилятору, что bar
- это имя шаблона, чтобы он знал, что <
запускает список аргументов шаблона и не является оператором меньше чем:
template<char> void bar() = delete;
int main() {
ns::Obj obj;
foo(obj); // Compile
bar<int>(obj); // Now compiles too
return 0;
}
Обратите внимание, что для перегрузки bar
необходимо быть шаблоном функции . Подпись не имеет значения, если она не так хороша, чтобы мешать разрешению перегрузки; ()
- хороший выбор, потому что по определению мы передаем хотя бы один аргумент, поэтому шаблон функции, не имеющий параметров, никогда не сможет быть жизнеспособным.
В качестве альтернативы, вы можете изменить bar
, чтобы вывести T
из аргумента тега:
template<class T>
struct type {};
namespace ns{
struct Obj {
// ...
template<typename T>
friend void bar(Obj, type<T>) { /* ... */ }
};
}
// ...
bar(obj, type<int>()); // OK
В C ++ 20 компилятор будет предполагать, что bar
называет шаблон, когда видит <
, и поиск имени ничего не находит, поэтому ваш код просто будет работать .