In the snippet below, I'm puzzled about why the definition of Wrapper::f() const
does not make my program ill-formed1 although it calls a non-const member function of a non mutable member variable:
// well-formed program (???)
// build with: g++ -std=c++17 -Wall -Wextra -Werror -pedantic
template<class T> struct Data { void f() {} };
template<class T> struct Wrapper
{
Data<T> _data;
void f() const { _data.f(); } // _data.f(): non-const!
};
int main()
{
Wrapper<void> w; // no error in instantiation point?
(void) w;
}
demo2
On the other hand, if Data
is a non template class3, a diagnostic is issued by my compiler:
// ill-formed program (as expected)
// build with: g++ -std=c++17 -Wall -Wextra -Werror -pedantic
struct Data { void f() {} };
template<class T> struct Wrapper
{
Data _data;
void f() const { _data.f(); } //error: no matching function for call to 'Data::f() const'
};
int main()
{
Wrapper<void> w;
(void) w;
}
I feel like the answer will contain expressions such as "deduced context" ... but I really cannot pin down the exact part of the standard scecifying this behaviour.
Is there a language lawyer to enlighten me on the matter?
Notes:
1) But I get an error if I try and effectively call Wrapper<T>::f() const
.
2) I've compiled with -std=c++17
but this is not specific to C++17, hence no specific tag.
3) In this answer, @Baum mit Augen quotes [N4140, 14.7.1(2)]
:
the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist
but here in the compiling snippet (#2) void f() const { _data.f(); }
fails although its "specialization is never referenced in a context that requires the member definition to exist".
constexpr if
... – YSC