// 1 filename:cpp2011-14-7-3.cpp
// ver 0.1 June.15, 2014
//
// 2 original examples and/or notes:
// (c) ISO/IEC JTC1 SC22 WG21 N3242, April 12, 2011
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
// >14 Templates 14.7 Template instantiation and specialization 14.7.3 Explicit specialization
// (c) Dr. OGAWA Kiyoshi, kaizen at gifu-u.ac.jp,
//
// 4 compile errors and/or warnings:
// 4.1(c) Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
// Target: x86_64-apple-darwin13.2.0,  Thread model: posix
// Command/Options: c++ -std=c++11 -stdlib=libc++ -Wall cpp2011-14-7-3.cpp
// (c) LLVM 2003-2009 University of Illinois at Urbana-Champaign.

// 4.2. g++-4.9 (GCC) 4.9.0 20131229 (experimental)
// Copyright (C) 2013 Free Software Foundation, Inc.
// This is free software; see the source for copying conditions.  
// There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// http://gcc.gnu.org/onlinedocs/gcc/Standards.html
// Command/Options: g++-4.9  -std=c++11  -Wall cpp2011-14-7-3.cpp 
// g++-4.9: error: unrecognized command line option '-stdlib=libc++'
// Configuration:brew install gcc49
//
// 4.3. Visual Studio Express 2013, 
// (c) Microsoft http://www.visualstudio.com/
// SPEC:
// Windows 7, .NET Framework
// (c) VMware, Inc.
// VMWare fusion 6
//
// 5. Hardware:  MacBook Pro, 
//(c) Intel http://ark.intel.com/products/37006/
//Core 2 Duo 2.53GHz, 8GB, 1067MHz DDR3
//
// 6. Special Thanks: Upper organizatios and 
// ITSCJ/IPSJ http://www.itscj.ipsj.or.jp/itscj_english/index.html
// Renesas Electronics Corporation.http://www.renesas.com/
// NPO SESSAME project, http://www.sessame.jp/workinggroup/WorkingGroup3/
// Toyo Corporation, http://www.toyo.co.jp/English/
// Japan Standard Association, http://bit.ly/1lzykg1
// NPO TOPPERS project, https://www.toppers.jp/asp-d-download.html
// Daido Universcity, http://www.daido-it.ac.jp/gakubugakka/computer/index.html
// WITZ Co.Ltd., http://www.witz-inc.co.jp/products/solution/solution.html
// SevenWise.co., http://www.7ws.co.jp/index.html
// TOYOTA Motor Corporation, http://toyota.jp/
// IT planning Inc., http://www.itpl.co.jp/en/index.html
// DENSO Corporation, http://www.globaldenso.com/en/
// Aisin Seiki co. Ltd., http://www.aisin.com/
// Spancion Inc., http://www.spansion.com/
// Yazaki Corporation, http://www.yazaki-group.com/global/
// Pananosic Corporation, http://www.panasonic.net/
// SWEST: Summer Workshop on Embedded System Technologies , http://swest.toppers.jp
// CEST: Consortium for Embedded System Technology, http://www.ertl.jp/CEST/
// JUSE: Union of Japanese Scientists and Engineers, http://www.juse.or.jp/e/
// OSC:Open Source Conference, http://www.ospn.jp/

#include <iostream>
#include <cstdlib>
#include <string.h>
#include <cstring>
#include <type_traits>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <complex>
#include <ccomplex>
#include <cstddef>
#include <new>
#include <vector>
#include <valarray>

using namespace std;

explicit-specialization:
template < > declaration
//
template<class T> class stream;
template<> class stream<char> { /* ... */ };
template<class T> class Array { /* ... */ };
template<class T> void sort(Array<T>& v) { /* ... */ }
template<> void sort<char*>(Array<char*>&) ;
//
//error: template<> class X<int> { /* ... */ }; // error: X not a template
template<class T> class X;
template<> class X<char*> { /* ... */ }; // OK: X is a template
//
template<class T> struct A {
void f(T) { /* ... */ }
};
template<> struct A<int> {
void f(int);
};
void h() {
A<int> a;
a.f(16); // A<int>::f must be defined somewhere
}
// explicit specialization syntax not used for a member of
// explicitly specialized class template specialization
void A<int>::f(int) { /* ... */ }
//
class String { };
template<class T> class Array1 { /* ... */ };
template<class T> void sort2(Array1<T>& v) { /* ... */ }
void f(Array1<String>& v) {
sort2(v); // use primary template
// sort(Array<T>&), T is String
}
template<> void sort2<String>(Array1<String>& v); // error: specialization
// after use of primary template
template<> void sort2<>(Array1<char*>& v); // OK: sort<char*> not yet used
//
namespace N {
template<class T> class X { /* ... */ };
template<class T> class Y { /* ... */ };
template<> class X<int> { /* ... */ }; // OK: specialization
// in same namespace
template<> class Y<double>; // forward declare intent to
// specialize for double
}
template<> class N::Y<double> { /* ... */ }; // OK: specialization
// in same namespace
//
template<class T> class X4; // X is a class template
template<> class X4<int>;
X4<int>* p; // OK: pointer to declared class X<int>
//error: X4<int> x; // error: object of incomplete class X<int>
//
template<class T> class Array2 { /* ... */ };
template<class T> void sort(Array2<T>& v);
// explicit specialization for sort(Array<int>&)
// with deduced template-argument of type int
template<> void sort(Array2<int>&);
//
template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }
template<> inline void f<>(int) { /* ... */ } // OK: inline
template<> int g<>(int) { /* ... */ } // OK: not inline
//
template<> X3 Q<int>::x; // declaration
//error: template<> X3 Q<int>::x (); // error: declares a function
template<> X3 Q<int>::x { }; // definition
//
template<class T> struct A5 {
void f(T);
template<class X1> void g1(T, X1);
template<class X2> void g2(T, X2);
void h(T) { }
};
// specialization
template<> void A5<int>::f(int);
// out of class member template definition
template<class T> template<class X1> void A5<T>::g1(T, X1) { }
// member template specialization
template<> template<class X1> void A5<int>::g1(int, X1);
//member template specialization
template<> template<>
void A5<int>::g1(int, char); // X1 deduced as char
template<> template<>
void A5<int>::g2<char>(int, char); // X2 specified as char
// member specialization even if defined in class definition
template<> void A5<int>::h(int) { }
//
template<class T1> class A6 {
template<class T2> class B {
void mf();
};
};
template<> template<> class A6<int>::B<double>;
template<> template<> void A6<char>::B<char>::mf();
//
template <class T1> class A7 {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template <> template <class X>
class A7<int>::B {
template <class T> void mf1(T);
};
template <> template <> template<class T>
void A7<int>::B<double>::mf1(T t) { }
template <class Y> template <>
void A7<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but
// its enclosing class template A is not
//
int main() {
	//
	cout << "14 Templates 14.7 Template instantiation and specialization 14.7.3 Explicit specialization" << std::endl;
	return 0;
}
// 1 error
//1.1 llvm: c++ -std=c++11 -stdlib=libc++  -Wall cpp2011-14-7-3.cpp
cpp2011-14-7-3.cpp:75:9: error: expected unqualified-id
explicit-specialization:
        ^
cpp2011-14-7-3.cpp:79:18: error: explicit specialization of non-template class 'stream'
template<> class stream<char> { /* ... */ };
                 ^     ~~~~~~
cpp2011-14-7-3.cpp:109:17: error: explicit specialization of 'sort2<String>' after instantiation
template<> void sort2<String>(Array1<String>& v); // error: specialization
                ^
cpp2011-14-7-3.cpp:106:1: note: implicit instantiation first required here
sort2(v); // use primary template
^
cpp2011-14-7-3.cpp:140:12: error: unknown type name 'X3'
template<> X3 Q<int>::x; // declaration
           ^
cpp2011-14-7-3.cpp:140:1: error: extraneous 'template<>' in declaration of variable 'Q'
template<> X3 Q<int>::x; // declaration
^~~~~~~~~~
cpp2011-14-7-3.cpp:140:16: error: expected ';' at end of declaration
template<> X3 Q<int>::x; // declaration
               ^
               ;
cpp2011-14-7-3.cpp:140:16: error: expected unqualified-id
cpp2011-14-7-3.cpp:142:12: error: unknown type name 'X3'
template<> X3 Q<int>::x { }; // definition
           ^
cpp2011-14-7-3.cpp:142:1: error: extraneous 'template<>' in declaration of variable 'Q'
template<> X3 Q<int>::x { }; // definition
^~~~~~~~~~
cpp2011-14-7-3.cpp:142:16: error: expected ';' at end of declaration
template<> X3 Q<int>::x { }; // definition
               ^
               ;
cpp2011-14-7-3.cpp:142:16: error: expected unqualified-id
cpp2011-14-7-3.cpp:185:24: error: nested name specifier 'A7<Y>::B<double>::' for declaration does not refer into a class, class template or class template
      partial specialization
void A7<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but
     ~~~~~~~~~~~~~~~~~~^
12 errors generated.