I have the following code:
template <class T>
class lit {
public:
lit(T l) : val(l) {}
T val;
};
template <class T>
class cat {
public:
cat(lit<T> const& a, lit<T> const& b) : a(a), b(b) {}
lit<T> const& a;
lit<T> const& b;
};
template <class T>
cat<T> operator+(lit<T> const& a, lit<T> const& b) {
return cat(a, b);
}
int main() {
auto r1 = cat((lit ('b')), lit('d')); // compiles
auto r2 = (lit ('b')) + lit('d') ; // doesn't compile
auto r3 = lit ('b') + lit('d') ; // compiles
auto r4 = (lit ('b')) ; // compiles
auto r5 = (lit<char>('b')) + lit('d') ; // compiles
}
This compiles fine with clang (as I would expect), but gcc produces the following error:
prog.cc: In function 'int main()':
prog.cc:23:20: error: missing template arguments after 'lit'
auto r2 = (lit ('b')) + lit('d') ; // doesn't compile
^~~
prog.cc:2:7: note: 'template<class T> class lit' declared here
class lit : public ExpressionBuilder<T> {
^~~
It seems to not be able to figure out the class template deduction from the constructor only in one very specific case (r2
). I am assuming gcc is wrong, but can someone explain why it would fail only in this very specific case?
Example here: https://wandbox.org/permlink/jQCOhXFFQekS17Y1
This is a brand new feature in C++17, and therefore brand new in GCC. The pattern you've observed — or lack thereof — looks very much like a compiler bug. The way that it is triggered apparently randomly also fits that pattern.
Delving further into the exact hows and whys is a tedious job for the GCC devs, not for a Stack Overflow answer, as it's likely to be extraordinarily complex… but the correct approach now is to raise a bug and watch what happens. (OP has now done that, as bug 87709.)
Related examples do already exist on Bugzilla.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With