从MS Visual Studio 2008迁移到MS Visual Studio 2017并使用v140工具集进行编译后,我遇到了定义类中是否存在特定成员变量的问题。 在我的例子中,它不是一个简单的变量,而是一个静态const引用。 它在2008年下运作良好。
以下是我的代码中没有编译的摘录
#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;
}
在我的原始代码中,错误是:“指向引用成员的指针是非法的”,参考:
enum { UseAutoIncrement = ( sizeof( f< Entry >( 0, 0 ) ) == sizeof( int ) ) };
这里错误是
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
答案 0 :(得分:1)
您可以将AutoIncrementName
修改为std::string
对象,而不是参考,以便您可以获取其地址。或者像这样更改两个f()
方法:
template< typename T >
static int f( decltype(&T::AutoIncrementName)*, void* );
template< typename T >
static char f( decltype(&T::AutoIncrementName)*, ... );
非类型模板参数有一些限制[temp.arg.nontype]/2:
2非类型模板参数的 template-argument 应为模板参数类型的转换常量表达式(8.20) 。对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或者对于指针类型,不应是地址):
- (2.1)子对象(4.5),
- (2.2)临时对象(15.2),
- (2.3)字符串文字(5.13.5),
- (2.4)
的结果typeid
表达式(8.2.8)或- (2.5)预先定义的
__func__
变量(11.4.1)。