C++成员模板特化语法疑问:类外定义显式特化成员规则解析
Let me break this down with plain language and concrete code examples to clarify the rule and what that "otherwise" refers to.
First, let's restate the core rule in simpler terms:
When defining a member outside an explicitly specialized class template:
- You don’t need
template<>syntax for most cases. - The only exception is if you’re defining a member of an explicitly specialized member class template (more on that below).
- Otherwise (the scenario you’re confused about), you need to use
template<parameters>for nested member templates that haven’t been specialized.
Let’s walk through each scenario with code:
Case 1: Defining a non-template member of a specialized class
This is the basic case where no template syntax is required.
// Original class template template<typename T> class MyClass { public: void print(); }; // Explicit specialization of MyClass for int template<> class MyClass<int> { public: void print(); // Declare here, define outside }; // Define the non-template member (no template syntax needed) void MyClass<int>::print() { std::cout << "MyClass<int>::print()\n"; }
Case 2: Defining a member of an explicitly specialized member class template
This is the "unless" exception mentioned in the rule. If the member belongs to a member class template that’s already been specialized, you still don’t need template<>.
// Original class template with a member class template template<typename T> class MyClass { public: template<typename V> class NestedClass { void nested_print(); }; }; // Explicit specialization of MyClass for int template<> class MyClass<int> { public: // Explicitly specialize the nested class for double template<> class NestedClass<double> { void nested_print(); // Declare here, define outside }; }; // Define the member of the specialized nested class (no template syntax needed) void MyClass<int>::NestedClass<double>::nested_print() { std::cout << "MyClass<int>::NestedClass<double>::nested_print()\n"; }
Case 3: The "Otherwise" Scenario
This refers to when you’re defining a member template that’s still generic (not specialized) inside the explicitly specialized outer class. Here, you must use template<parameters> for the member template itself.
// Original class template with a member function template template<typename T> class MyClass { public: template<typename U> void print(U val); }; // Explicit specialization of MyClass for int template<> class MyClass<int> { public: // Keep the member template generic (not specialized) template<typename U> void print(U val); // Declare here, define outside }; // Define the generic member template (requires template<U> prefix) template<typename U> void MyClass<int>::print(U val) { std::cout << "MyClass<int>::print(U): " << val << "\n"; }
To sum up the "otherwise" part:
- What it means: You’re defining a member template (function or class) that hasn’t been explicitly specialized in the outer class’s specialization. The member remains a generic template even after the outer class is specialized.
- Syntax requirement: You must prefix the definition with
template<parameters>where the parameters match the member template’s own template arguments.
内容的提问来源于stack exchange,提问作者user42768

