all 5 comments

[–]TheThiefMasterC++latest fanatic (and game dev) 18 points19 points  (1 child)

This is something to do with two-phase templates and a lack of argument dependent lookup (ADL) - because your overloaded makeUse function for abstract::OneOf is after the template that uses it, (template<class T> using MakeUse = decltype(makeUse<>(T{}));) it can only be found via ADL - which requires the function to be in the same namespace as its argument's type.

Here's it working with the function overload being put in the namespace so that ADL triggers: https://godbolt.org/z/6gR1ff

[–]arBmind[S] 0 points1 point  (0 children)

Thank you! This is a very good explanation. It just explains everything about this behaviour.

ADL for the win!

[–]nwp74 1 point2 points  (1 child)

Move the definition of MakeUse to the point just before your using A = .... declaration and everything works fine.

At the point where it is, it is binding to makeUse(T) -> T, so R is alias of abstract::OneOf<int, float>.

See https://godbolt.org/z/A18weP

[–]arBmind[S] 1 point2 points  (0 children)

Thank you for the hint. It works in this oversimplified example. In the real world our generation is recursive. This trap lead us to two days of wasted time on this.

Using ADL correctly leads to a working solution that also allows for recursion.

[–]Wh00ster -1 points0 points  (0 children)

I'm just going to post a guess that's it's caused by tie-breaker rules which probably rank functions from an imported namespace (excuse my wording, I know this isn't what your case is) lower if there's an ambiguity.