degawong
degawong

Reputation: 49

visual studio bug or c++ standard changed?

#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

Answers (2)

Swift - Friday Pie
Swift - Friday Pie

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

Robert Andrzejuk
Robert Andrzejuk

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

Related Questions