AG
Size: a a a
AG
LA
Е
A
AG
K
A
K
K
K
A
K
Е
LA
AM
AS
VS
#include <iostream>
template<typename T>
struct X {
void foo() {
std::cout << "foo in-class";
}
// deleted __definition__
// declaration would be void bar()
void bar() = delete;
void baz() {
std::cout << "baz in-class";
}
void qux() = delete;
};
// specialization 1
template<>
void X<int>::foo() {
std::cout << "foo spec";
}
// specialization 2
template<>
void X<int>::bar() {
std::cout << "bar spec";
}
int main() {
X<int> x; // 1
x.foo(); // 2
x.bar(); // 3
x.baz(); // 4
x.qux(); // 5
}
// specialization 3, IFNDR
template<>
void X<int>::qux() {
std::cout << "qux spec";
}
0) к моменту компиляции main()
компилятору известно следующее: определение шаблона класса A
с определением всех членов, и declared specializations A<int>::foo()
и A<int>::bar()
, которые являются определяющими объявлениями (basic#def-2)X<int>
. в явном виде эта специализация ни объявлена, ни определена, поэтому определение генерируется согласно temp.spec#temp.inst-2 и следующего за ним пункта 3:template<>
class X<int> {
// declaration from spec 1
void foo();
// declaration from spec 2
void bar();
// 3.1, declaration
void baz();
// 3.2, (deleted) definition
void qux() = delete;
};
зато в точке 1 компилятор знает о существовании специализаций 1 и 2 (их объявления требует temp.spec#temp.expl.spec-7.sentence-1), и использует их объявления в специализации класса. temp.spec#temp.inst-3 для них не работает ввиду temp.spec#temp.inst-11.sentence-1 (*)X<int>::foo()
в X<int>
. выбор очевиден, полагаю.X<int>::foo()
. известно, что эта декларация пришла из declared specialization, поэтому определение берется оттуда.x.bar()
ситуация полностью аналогична x.foo()
, несмотря на то, что в шаблоне класса она является удаленной функцией.X<int>::baz()
известно только объявление. так как оно было неявно сгенерировано в отсутствие declared specialization, то и определение будет неявно сгенерировано согласно temp.spec#temp.inst-4X<int>::qux() = delete
7) на момент, когда о специализации 3 становится известно, определение X<int>::qux() = delete
уже сгенерировано (п. 1), поэтому она является переопределением и нарушает ODRVS
K
VS