Reputation: 49
#include <iostream>
template<typename T>
struct base {
void hello() {
}
};
template<typename T>
struct ttt : public base<ttt<T>> {
public:
ttt() {
hello();
}
};
int main() {
ttt<int> t();
return 0;
}
when i use c++ 17 or 11, this code is just ok. but when i set the c++ standard to 20, the C3816 error occurred says can not find hello function, i am confused about the reason, why this error comes until c++ 20.
Upvotes: 1
Views: 606
Reputation: 14614
The hello();
statement isn't dependent on template argument and there is no such name in immediate search context (ie. inside of ttt
or its non-template base class if any), so name look up would be done in non-template context. I.e. if you had a global function named hello
, it will be chosen instead. This is dictated by every standard, at least since C++11. A standard compliant way to do that is to make prvalue dependant on argument of template:
this->hello(); // this is dependant on T
Another way is use of a fully qualified name using base<ttt<T>>::
prefix, but that implies that only that version of function can be chosen. If ttt
will override it, if inheritance tree will expand and there will be another overload\override of hello
, if a multiple virtual inheritance will be present, such qualified name might be pointing at unintended function member.
The bug in Visual Studio goes back as far as VS2010 at least, I personally suffered from it for years because developers would write code that compiles using MSVC bu wouldn't be compiled by gcc and I had to explain them what's wrong, every time ("But it compiles!").
Upvotes: 6
Reputation: 5232
This is a change of default settings.
Starting in Visual Studio 2019 version 16.8, the /std:c++latest option implicitly sets the /permissive- option.
https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-160
To fix the code prefix the function name with the base class name:
base<ttt<T>>::hello();
At the top of my class I like to add :
using Base = base<ttt<T>>;
Then I can call :
Base::hello();
Upvotes: 1