Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Explicit (full) template specialization

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Template specialization
      Parameter packs(C++11)
      Miscellaneous
       
      Declarations
       
      Expressions
      General
      Literals
      Operators
      Conversions
       
       

      Allows customizing the template code for a given set of template arguments.

      Contents

      [edit]Syntax

      template <>declaration

      Any of the following can be fully specialized:

      1. function template
      2. class template
      3. variable template(since C++14)
      4. member function of a class template
      5. static data member of a class template
      6. member class of a class template
      7. memberenumeration of a class template
      8. member class template of a class or class template
      9. member function template of a class or class template
      10. member variable template of a class or class template(since C++14)

      For example,

      Run this code
      #include <type_traits> template<typename T>// primary templatestruct is_void:std::false_type{};template<>// explicit specialization for T = voidstruct is_void<void>:std::true_type{}; int main(){    static_assert(is_void<char>::value==false,"for any type T other than void, the class is derived from false_type");    static_assert(is_void<void>::value==true,"but when T is void, the class is derived from true_type");}

      [edit]In detail

      Explicit specialization may be declared in any scope where its primary template may be defined (which may be different from the scope where the primary template is defined; such as with out-of-class specialization of amember template). Explicit specialization has to appear after the non-specialized template declaration.

      namespace N{template<class T>// primary templateclass X{/*...*/};template<>// specialization in same namespaceclass X<int>{/*...*/}; template<class T>// primary templateclass Y{/*...*/};template<>// forward declare specialization for doubleclass Y<double>;} template<>// OK: specialization in same namespaceclass N::Y<double>{/*...*/};

      Specialization must be declared before the first use that would cause implicit instantiation, in every translation unit where such use occurs:

      class String{}; template<class T>class Array{/*...*/}; template<class T>// primary templatevoid sort(Array<T>& v){/*...*/} void f(Array<String>& v){    sort(v);// implicitly instantiates sort(Array<String>&),}// using the primary template for sort() template<>// ERROR: explicit specialization of sort(Array<String>)void sort<String>(Array<String>& v);// after implicit instantiation

      A template specialization that was declared but not defined can be used just like any otherincomplete type (e.g. pointers and references to it may be used):

      template<class T>// primary templateclass X;template<>// specialization (declared, not defined)class X<int>; X<int>* p;// OK: pointer to incomplete typeX<int> x;// error: object of incomplete type

      Whether an explicit specialization of a function or variable(since C++14) template isinline/constexpr(since C++11)/constinit/consteval(since C++20) is determined by the explicit specialization itself, regardless of whether the primary template is declared with that specifier. Similarly,attributes appearing in the declaration of a template have no effect on an explicit specialization of that template:(since C++11)

      template<class T>void f(T){/* ... */}template<>inlinevoid f<>(int){/* ... */}// OK, inline template<class T>inline T g(T){/* ... */}template<>int g<>(int){/* ... */}// OK, not inline template<typename>[[noreturn]]void h([[maybe_unused]]int i);template<>void h<int>(int i){// [[noreturn]] has no effect, but [[maybe_unused]] has}

      [edit]Explicit specializations of function templates

      When specializing a function template, its template arguments can be omitted iftemplate argument deduction can provide them from the function arguments:

      template<class T>class Array{/*...*/}; template<class T>// primary templatevoid sort(Array<T>& v);template<>// specialization for T = intvoid sort(Array<int>&); // no need to write// template<> void sort<int>(Array<int>&);

      A function with the same name and the same argument list as a specialization is not a specialization (see template overloading infunction template).

      Default function arguments cannot be specified in explicit specializations of function templates, member function templates, and member functions of class templates when the class is implicitly instantiated.

      An explicit specialization cannot be afriend declaration.

      This section is incomplete
      Reason: review the exception specification requirement across different C++ versions

      [edit]Members of specializations

      When defining a member of an explicitly specialized class template outside the body of the class, the syntaxtemplate<> is not used, except if it's a member of an explicitly specialized member class template, which is specialized as a class template, because otherwise, the syntax would require such definition to begin withtemplate<parameters> required by the nested template

      template<typename T>struct A{struct B{};// member class template<class U>// member class templatestruct C{};}; template<>// specializationstruct A<int>{void f(int);// member function of a specialization};// template<> not used for a member of a specializationvoid A<int>::f(int){/* ... */} template<>// specialization of a member classstruct A<char>::B{void f();};// template<> not used for a member of a specialized member class eithervoid A<char>::B::f(){/* ... */} template<>// specialization of a member class templatetemplate<class U>struct A<char>::C{void f();}; // template<> is used when defining a member of an explicitly// specialized member class template specialized as a class templatetemplate<>template<class U>void A<char>::C<U>::f(){/* ... */}


      An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. These definitions must use braces for default initialization:

      template<>X Q<int>::x;// declaration of a static membertemplate<>X Q<int>::x();// error: function declarationtemplate<>X Q<int>::x{};// definition of a default-initialized static member

      A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition.

      template<typename T>struct A{void f(T);// member, declared in the primary template void h(T){}// member, defined in the primary template template<class X1>// member templatevoid g1(T, X1); template<class X2>// member templatevoid g2(T, X2);}; // specialization of a membertemplate<>void A<int>::f(int); // member specialization OK even if defined in-classtemplate<>void A<int>::h(int){} // out of class member template definitiontemplate<class T>template<class X1>void A<T>::g1(T, X1){} // member template specializationtemplate<>template<class X1>void A<int>::g1(int, X1); // member template specializationtemplate<>template<>void A<int>::g2<char>(int,char);// for X2 = char // same, using template argument deduction (X1 = char)template<>template<>void A<int>::g1(int,char);

      A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, there's atemplate<> for everyenclosing class template that is explicitly specialized.

      template<class T1>struct A{template<class T2>struct B{template<class T3>void mf();};}; template<>struct A<int>; template<>template<>struct A<char>::B<double>; template<>template<>template<>void A<char>::B<char>::mf<double>();

      In such a nested declaration, some of the levels may remain unspecialized (except that it can't specialize a class member template in namespace scope if its enclosing class is unspecialized). For each of those levels, the declaration needstemplate<arguments>, because such specializations are themselves templates:

      template<class T1>class A{template<class T2>class B{template<class T3>// member templatevoid mf1(T3); void mf2();// non-template member};}; // specializationtemplate<>// for the specialized Atemplate<class X>// for the unspecialized Bclass A<int>::B{template<class T>void mf1(T);}; // specializationtemplate<>// for the specialized Atemplate<>// for the specialized Btemplate<class T>// for the unspecialized mf1void A<int>::B<double>::mf1(T t){} // ERROR: B<double> is specialized and is a member template, so its enclosing A// must be specialized alsotemplate<class Y>template<>void A<Y>::B<double>::mf2(){}

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 531C++98the syntax of defining members of explicit
      specializations in namespace scope was not specified
      specified
      CWG 727C++98partial and full specializations not allowed in
      class scope
      allowed in any scope
      CWG 730C++98member templates of non-template
      classes could not be fully specialized
      allowed
      CWG 2478C++20it was unclear whether theconstinit andconsteval of the
      primary template are carried over into its explicit specializations
      not carried over
      CWG 2604C++11it was unclear whether the attributes of the primary
      template are carried over into its explicit specializations
      not carried over

      [edit]See also

      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/template_specialization&oldid=170153"

      [8]ページ先頭

      ©2009-2025 Movatter.jp