You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] UFCS with variable template in scope fails #807
std::vector<int>().empty() will fail given using std::views::empty;.
That should end up calling the member empty of std::vector.
But the UFCS macro fails on the free function branch.
This issue came up while implementing @rule_of_zero at #797.
Fortunately, I could fix it with a local using std::ranges::empty; // Pending #506.
(std::views::empty actually came from using namespace std::views;).
So it doesn't directly use std::vector::empty.
I was fortunate enough to have such a fix-hack at hand.
I think this one really is IFNDR.
Reading https://eel.is/c++draft/algorithms.requirements#2
reminded me that the else branch,
although never taken for std::vector,
will always be ill-formed for all invocations (because std::views::empty needs a template argument).
The one case we can handle is when source local name lookup results in a variable.
If it isn't templated, func<targs>(obj) can't be valid, so the only option is the member call.
See https://cpp2.godbolt.org/z/T6sdezYKh:
t: @struct type = {
f: <T> (this) = { }
g: <T> (this) = { }
}
main: () = {
t().f<int>(); // OK.
g := 0;
// error: 'g' does not name a template but is followed by template arguments
t().g<int>();
_ = g;
}
automain() -> int{
CPP2_UFCS_TEMPLATE(f<int>)(t());// OK.auto g {0};
CPP2_UFCS_TEMPLATE(g<int>)(t());// Sstatic_cast<void>(std::move(g));
}
main.cpp2:10:22: error: 'g' does not name a template but is followed by template arguments
10 | CPP2_UFCS_TEMPLATE(g<int>)(t());
| ^~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:855:84: note: expanded from macro 'CPP2_UFCS_TEMPLATE'
855 | #define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,(),template,__VA_ARGS__)
| ^~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:845:51: note: expanded from macro 'CPP2_UFCS_'
845 | noexcept(CPP2_UFCS_IS_NOTHROW_ARG(QUALID,TEMPKW,__VA_ARGS__)) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \
| ^~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:803:90: note: expanded from macro 'CPP2_UFCS_IS_NOTHROW_ARG'
803 | #define CPP2_UFCS_IS_NOTHROW_ARG(QUALID,TEMPKW,...) CPP2_UFCS_IS_NOTHROW(QUALID,TEMPKW,__VA_ARGS__)
| ^~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:801:60: note: expanded from macro 'CPP2_UFCS_IS_NOTHROW'
801 | requires noexcept(CPP2_UFCS_REMPARENS QUALID __VA_ARGS__(std::declval<Obj>(), std::declval<Params>()...)); }
| ^~~~~~~~~~~
main.cpp2:8:8: note: non-template declaration found by name lookup
8 | auto g {0};
| ^
Activity
JohelEGP commentedon Nov 5, 2023
I noticed the same failure if you attempt to call
std::vector<int>().std::vector<int>::empty()(https://cpp2.godbolt.org/z/c5veMnjMe).Branch
main: https://compiler-explorer.com/z/9oa1Ga3Tx (but see #555).#506: https://compiler-explorer.com/z/qvK7E4Kj8.
Except that Clang's error message requests for disambiguating
template.This issue came up while implementing
@rule_of_zeroat #797.Fortunately, I could fix it with a local
using std::ranges::empty; // Pending #506.(
std::views::emptyactually came fromusing namespace std::views;).So it doesn't directly use
std::vector::empty.I was fortunate enough to have such a fix-hack at hand.
JohelEGP commentedon Nov 7, 2023
I think this one really is IFNDR.
Reading https://eel.is/c++draft/algorithms.requirements#2
reminded me that the else branch,
although never taken for
std::vector,will always be ill-formed for all invocations (because
std::views::emptyneeds a template argument).JohelEGP commentedon Nov 7, 2023
IIRC from my analysis at #307, it's that this can't be solved without Cpp1 reflection.
JohelEGP commentedon Nov 9, 2023
The same seems to happen for
operator(): https://compiler-explorer.com/z/65Y5rh7P5.JohelEGP commentedon Dec 13, 2023
The one case we can handle is when source local name lookup results in a variable.
If it isn't templated,
func<targs>(obj)can't be valid, so the only option is the member call.See https://cpp2.godbolt.org/z/T6sdezYKh: