Рассмотрим следующий пример, состоящий из 4 файлов.
Внешний.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
.
Насколько я понимаю, это законно, поскольку согласно 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 ошибаются?
ОБНОВЛЕНИЕ: я считаю, что нашел соответствующий отрывок в §14.7.2 [templ.explicit] (пункт 12) n4296 и n4567 рабочие проекты стандарта:
Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров. [Примечание. В частности, аргументы и имена шаблонов, используемые в деклараторе функций (включая типы параметров, возвращаемые типы и спецификации исключений), могут быть частными типами или объектами, которые обычно недоступны, а шаблон может быть шаблоном-членом или функцией-членом. который обычно недоступен. — примечание в конце]
Если я не ошибаюсь в том, что написано, кажется, что такое поведение MSVC действительно не соответствует требованиям. Конечно, это всего лишь черновики — у меня, к сожалению, нет доступа к фактическим 133 доллара США за копию стандартно, поэтому я не могу быть уверен, что этот элемент сохранен.