考虑以下示例,包含4个文件。
的 Outer.h
#pragma once
#include "genericAlgorithm.h"
class Outer
{
private:
struct Inner {}; // Note that Inner is private
const Inner inner;
public:
Outer() : inner() {}
inline void method()
{
genericAlgorithm(inner);
}
};
的 genericAlgorithm.h
#pragma once
template <typename T>
void genericAlgorithm(const T& value);
的 genericAlgorithm.cpp
#include "genericAlgorithm.h"
#include "Outer.h"
template <typename T>
void genericAlgorithm(const T& value) {}
// Explicit template instantiation (compiles on GCC, Clang; error C2248 on MSVC)
template void genericAlgorithm<Outer::Inner>(const Outer::Inner& value);
的的main.cpp
#include "Outer.h"
int main()
{
Outer outer;
outer.method();
return 0;
}
正如您所看到的,genericAlgorithm.cpp
中有genericAlgorithm()
函数模板的显式实例化,用于参数Outer::Inner
,它是类Outer
的私有内部结构。< / p>
据我所知,这是合法的,因为cppreference.com ......
显式实例化定义忽略成员访问说明符:参数类型和返回类型可以是私有的。
事实上,这段代码在GCC 6.3和Clang 4.0上编译得非常好。
但是, MSVC(Visual Studio 2017 15.2)似乎对它有疑问并产生以下编译错误:
genericalgorithm.cpp(9): error C2248: 'Outer::Inner': cannot access private struct declared in class 'Outer'
那么,这是MSVC中的一个错误还是我遗漏了一些东西,实际上我的代码有问题需要修复?如果是这样,是不是意味着它是GCC和Clang,还有cppreference.com,谁错了?
更新:我相信我在n4296和n4567标准工作草案的§14.7.2[templ.explicit](第12项)中找到了相关段落:
通常的访问检查规则不适用于用于指定显式实例化的名称。 [注意:在 特别是,函数声明符中使用的模板参数和名称(包括参数类型, 返回类型和异常规范)可以是通常不属于的私有类型或对象 可访问的,模板可以是通常不会的成员模板或成员函数 无障碍。 - 结束说明]
除非我误解了所写的内容,否则MSVC的这种行为似乎确实是不合规的。当然,这些只是草稿 - 遗憾的是我无法访问实际的$133 per copy标准,因此我无法确定此项目是否已被保留。
答案 0 :(得分:0)
我会读到这意味着显式实例化定义会忽略中明确指定的内容中的访问说明符。它并不会神奇地授予您访问其他项目的私人成员的权限。
Type&#34; Inner&#34;对于您用作参数的东西是私有的,而不是键入genericAlgorithm