MSVC友元函数声明错误
MSVC friend function declaration bug
考虑以下代码:
#include <cstddef>
template<size_t value> class dummy { };
class my_class
{
int m_member;
// Overload 1
template<size_t value>
friend void friend_func(dummy<value>*);
// Overload 2
template<size_t value>
friend void friend_func(int(*)[value]);
};
// Overload 1
template<size_t value>
void friend_func(dummy<value>*)
{
my_class instance;
instance.m_member = value;
}
// Overload 2
template<size_t value>
void friend_func(int(*)[value])
{
my_class instance;
instance.m_member = value;
}
int main(int argc, char* argv[])
{
dummy<5> d;
friend_func(&d); // call Overload 1
int arr[5];
friend_func(&arr); // call Overload 2 - error in MSVC!
return 0;
}
可以看到,这两个函数之间的唯一区别是第二个函数使用指向value
int
s而不是dummy<value>
的指针。这段代码在GCC ($ GCC -4.7.2 test.cpp)和Clang(感谢WhozCraig)中编译得很好,但在MSVC(我测试了2012)中抛出以下错误:
1>d:pathto.cpp(32): error C2248: 'my_class::m_member' : cannot access private member declared in class 'my_class'
1> d:pathto.cpp(8) : see declaration of 'my_class::m_member'
1> d:pathto.cpp(7) : see declaration of 'my_class'
1> d:pathto.cpp(40) : see reference to function template instantiation 'void friend_func<5>(int (*)[5])' being compiled
对我来说,这看起来像一个bug。但是,以前有人遇到过这样的行为吗?这真的是一个bug吗,或者可能有一个特定的错误原因?有什么快速的解决方法吗?
编辑:我已经能够找到一个适当的解决方案,见下面的答案。
这绝对是一个错误:不能将数组大小参数化的模板函数声明为类的友元。当value
被推断为友模板函数的数组大小时,就会发生这种情况。以下是代码的简化版本,可以很好地编译。这个例子是完全相同的代码,除了我指定了数组的大小。
class my_class
{
int m_member;
template<size_t value>
friend void friend_func(int(*)[5]);
};
template<size_t value>
void friend_func(int(*)[5])
{
my_class instance;
instance.m_member = value;
}
int main()
{
int arr[5];
friend_func<5>(&arr);
}
一种解决方法是将value
作为第二个函数参数传递:
template <typename T>
void friend_func(T, int value)
{
my_class instance;
instance.m_member = value;
}
非常确定这是MSVS的已知问题。您的具体问题在boost.org上的可移植性提示:microsoft Visual c++中列出。
寻找模板作为朋友。我不知道周围的工作。然而,我认为你可以让一个班级成为朋友。你可以用它来解决这个问题。
我已经找到了一个解决方法,既保留了功能,又能防止错误消息的出现。其思想是使用代理函数和代理类来携带指向数组及其大小的指针。下面是解决方案:
#include <cstddef>
// Workaround class for a bug in MSVC.
// https://connect.microsoft.com/VisualStudio/feedback/details/717749
// http://stackoverflow.com/questions/15149607
template<class element_type, size_t count>
class friend_declaration_bug_workaround
{
public:
typedef element_type(*ptr_type)[count];
private:
ptr_type m_arr;
public:
explicit friend_declaration_bug_workaround(ptr_type arr)
: m_arr(arr)
{
}
ptr_type value() const
{
return m_arr;
}
};
class my_class
{
int m_member;
friend void friend_func(int*);
template<size_t value>
friend void friend_func_workaround(friend_declaration_bug_workaround<int, value>);
};
template<size_t value>
void friend_func_workaround(friend_declaration_bug_workaround<int, value> workaround)
{
my_class instance;
instance.m_member = (*workaround.value())[0];
}
void friend_func(int* arr)
{
my_class instance;
instance.m_member = *arr;
}
template<size_t value>
void friend_func(int(*arr)[value])
{
friend_declaration_bug_workaround<int, value> workaround(arr);
return friend_func_workaround(workaround);
}
int main(int argc, char* argv[])
{
int value;
friend_func(&value); // call non-templated function
int arr[5];
friend_func(&arr); // call workarounded function
return 0;
}
相关文章:
- 错误:未在此范围内声明'reverse'
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 从具有默认值的部分指定模板类继承时发生SWIG错误,具有不带默认值的正向声明
- 错误:"imread"未在此范围内声明
- 在气泡排序程序中未声明错误功能
- 使用全局声明的向量时,C++双重释放错误/损坏
- 使用直接大括号初始化时,C++ 编译错误"声明末尾的预期";"
- C++ [错误] 声明'char '隐藏参数。什么意思?
- 类中的静态函数给出了错误:声明中的两种或多个数据类型
- 错误:声明冲突 - 指针不能是 int
- 收到 CUDA 错误"声明与以前的"variable_name"不兼容
- 错误:声明不声明
- Visual Studio 2010 链接器错误C++声明我从头文件创建的类时
- Cython 错误:声明不声明任何内容
- 错误"声明非模板函数"C++
- 无效地使用不完整的类型/前向错误声明.可能误用抽象类?(c++)
- 错误:声明冲突.用c++编译c代码
- C++错误:声明中存在显式限定
- else语句(C++)上的错误w/声明
- 初始化const类成员,错误:声明没有声明任何内容