次のコードについて考えてみます。
#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;
}
ご覧のとおり、これら2つの関数の唯一の違いは、2番目の関数が。value
int
ではなくsへのポインターを受け取ることですdummy<value>
。このコードは、GCC($ gcc-4.7.2 test.cpp)とClang(WhozCraigに感謝)では問題なくコンパイルされますが、MSVCでは次のエラーがスローされます(2012年にテストしました)。
1>d:\path\to.cpp(32): error C2248: 'my_class::m_member' : cannot access private member declared in class 'my_class'
1> d:\path\to.cpp(8) : see declaration of 'my_class::m_member'
1> d:\path\to.cpp(7) : see declaration of 'my_class'
1> d:\path\to.cpp(40) : see reference to function template instantiation 'void friend_func<5>(int (*)[5])' being compiled
私にはこれはバグのように見えます。しかし、以前にそのような行動に遭遇した人はいますか?それは本当にバグですか、それともエラーの特定の理由がありますか?これに対する簡単な回避策はありますか?
編集:適切な回避策を見つけることができました。以下の回答を参照してください。