I have the following chunk of code which "works" in a simple, newly created hello world VS2017 project, and in another app we have, but for some reason I cannot identify, it doesn't "work" when I port it to the current app I'm working on.
/**
* This can be used to associate a class variable to a type and a string in order
* to load it easily from XML or JSON.
*/
template<typename Class, typename T>
struct Property {
constexpr Property( T Class::*aMember, const char* aName )
: member { aMember }, name { aName } {}
using Type = T;
using ClassType = Class;
T Class::*member;
const char* name;
};
struct MajorPaine
{
int mInt;
// All errors are "spammed" by the following line:
static constexpr auto perp = Property<MajorPaine, decltype(MajorPaine::mInt)>{
&MajorPaine::mInt, "int" };
};
When I compile this code, I get those errors (compiled with Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27034 for x86):
error C2327: 'MajorPaine::mInt': is not a type name, static, or enumerator
error C2065: 'mInt': undeclared identifier
fatal error C1903: unable to recover from previous error(s); stopping compilation
What could be the reason for the errors?
Answering my own question to help folks avoid spending hours on this (and my future self).
tldr: The compiler flag /permissive-
was not set. Setting it did fix it.
According to the help page for the /permissive- flag,
[...] The compiler also implements more of the requirements for two-phase name look-up. When the /permissive- option is set, the compiler parses function and class template definitions, and identifies dependent and non-dependent names used in the templates. [...]
So I assume that both errors stem from the fact that the compiler did a single pass at reading the struct, and did not know yet that mInt
did actually exist. Allowing the compiler to do two phases allows it to see the member and actually use it.
It's worth noting that "[...] By default, the /permissive- option is set in new projects created by Visual Studio 2017 version 15.5 and later versions. [...]". This is explains why it was working fine in a newly created VS project, and in the previous project I worked on, but not on the my current project (because it was created a while ago).