Reputation: 11
After migrating from MS Visual Studio 2008 to MS Visual Studio 2017 and compiling using v140 toolset, I got a problem with defining whether a specific member variable is present in class. In my case it not a simple variable but a static const reference. It worked fine in under 2008.
Here is an extract from my code which doesn't compile
#include <iostream>
#include <string>
struct ActivityEntry
{
static const std::string& AutoIncrementName;
};
template< typename Entry >
struct AutoIncrementNameSelect
{
template< const std::string* >
struct TestHasMember;
template< typename T >
static int f( TestHasMember< &T::AutoIncrementName >*, void* );
template< typename T >
static char f( TestHasMember< &T::AutoIncrementName >*, ... );
enum { UseAutoIncrement = ( sizeof( f< Entry >( 0, 0 ) ) == sizeof( int ) ) };
};
std::string s("aaa");
//initialize the reference
const std::string & ActivityEntry::AutoIncrementName(s);
int main()
{
std::cout<<"Use autoinc:"<< AutoIncrementNameSelect<ActivityEntry>::UseAutoIncrement;
return 0;
}
In my original code the error is: "pointer to reference member is illegal" with reference to:
enum { UseAutoIncrement = ( sizeof( f< Entry >( 0, 0 ) ) == sizeof( int ) ) };
Here, the error is
error: '& ActivityEntry::AutoIncrementName' is not a valid template argument for 'const string* {aka const std::basic_string*}' because it is not the address of a variable
Upvotes: 1
Views: 51
Reputation: 3911
You can modify the AutoIncrementName
to be a std::string
object, not a reference, so that you could take its address. Or change the two f()
methods like this:
template< typename T >
static int f( decltype(&T::AutoIncrementName)*, void* );
template< typename T >
static char f( decltype(&T::AutoIncrementName)*, ... );
Non-type template arguments have some limitations [temp.arg.nontype]/2:
2 A template-argument for a non-type template-parameter shall be a converted constant expression (8.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
—(2.1) a subobject (4.5),
—(2.2) a temporary object (15.2),
—(2.3) a string literal (5.13.5),
—(2.4) the result of a
typeid
expression (8.2.8), or—(2.5) a predefined
__func__
variable (11.4.1).
Upvotes: 1