template< typename T > //Primary template as we know
class A {
void print(){ std::cout << "Primary template" << std::endl; }
};template<>
class A< { char*, std::string, std::wstring } > { // Instead one type it is list of types.
void print(){ std::cout << "String specialization" << std::endl; }
};
HelloHere is simple idea how to use existing code to make several (partial) specialization at once.
Instead of one type use list of types.Quick example:template< typename T > //Primary template as we know
class A {
void print(){ std::cout << "Primary template" << std::endl; }
};template<>
class A< { char*, std::string, std::wstring } > { // Instead one type it is list of types.
void print(){ std::cout << "String specialization" << std::endl; }
};More details/examples in attachment.Source controlled file: https://github.com/dmilos/cpp_proposal/blob/master/multi_spec.htmlD.
template <typename T>
class A { ... };
template <typename T, typename... Us>
inline constexpr bool is_any_of_v = (std::is_same_v<T, Us> || ... );
template <typename T>
requires is_any_of_v<T, char*, std::string, std::wstring>
class A<T> { ... };
template <typename T>
concept StringLike = /* something sane */;
template <StringLike T>
class A<T> { ... };
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/90cc934f-8532-4110-8d73-2824dabd51ec%40isocpp.org.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/910830df-1a1c-4e32-8358-d24a4636d1b1%40isocpp.org.
Multiple (partial)specialization
Document number:
Date:
Reply to:
2018/02/12
Dejan D.M. Milosavljevic
(dmilos at gmail dot com)
Table of Contents.
I. Introduction II. Motivation and Scope III. Solutions IV. Design Decisions V. Impact On the Standard VI. References I. Introduction- Multiple (partial)specialization. This feature will allow multiple (partial)specialize of template without need for additional code. It is assumed that extra/additional code is something that comes after class definition or (partial) specialization.
II. Motivation and Scope- Usual problem with template specialization is how to reuse existing code for other type. One of idea is to have separate code for each type that will point to previous specialization. But this idea will rise more requests such as modification of existing functions and members. This idea avoid those request by use of existing code at point of (partial)specialization.
It is often that some types can be grouped in manner that share same class specialization. In presented example we have integer group( short, int, long ), rational ( float, double, long double ) and strng ( char*, std::string, std::wstring ).
- Problem 1:
- Lets make several groups of types. Each group heed their own specialization.
In next example we have two groups.
First group contain:char*
,std::string
,std::wstring
. Second group:float
,double
,long double
.
Note: This example can be extended with more groups like signed integers, unsigned integers.
[Example:—end example]
template< typename T > class A { void print(){ std::cout << "Primary template" << std::endl; } }; template<> class A< std::string > { void print(){ std::cout << "String specialization" << std::endl; } }; template<> class A< char* > { // NOTE: In here we keep "String specialization". void print(){ std::cout << "String specialization" << std::endl; } }; template<> class A< std::wstring > { // NOTE: In here we keep "String specialization". void print(){ std::cout << "String specialization" << std::endl; } }; template<> class A<float > { void print(){ std::cout << "Rational specialization" << std::endl; } }; template<> class A< double > { // NOTE: Same as foat void print(){ std::cout << "Rational specialization" << std::endl; } }; template<> class A< long double > { // NOTE: Same as foat void print(){ std::cout << "Rational specialization" << std::endl; } };- Problem 2:
- Lest start with some enum with enough large number of enumerants.
Goal is to specializeclass E
so the enum subgroups have same template specialization.
In this example first subgroup are consisted fromred
,green
,blue
.
Second subgroup:cyan
,yellow
andmagenta
.
[Example:—end example]
enum colors{ red, green, blue, cyan, magenta, yellow, orange, pink }; template< enum Colors color = red > class E { void print(){ std::cout << "Primary template with red default"<< std::endl; } }; template< > class E< green > { // In here we want to keep primary definition of print function void print(){ std::cout << "Primary template with red default"<< std::endl; } }; template< > class E< blue > { // In here we want to keep primary definition of print function void print(){ std::cout << "Primary template with red default"<< std::endl; } }; template< > class E< yellow > { // Brand new specialization of print function void print(){ std::cout << "YELLOW"<< std::endl; } }; template< > class E< magenta > { // Same as E< yellow > void print(){ std::cout << "YELLOW"<< std::endl; } }; // etc- Problem 3:
- Similarly like for enums, in here some groups of integers need to share same specialization. Specialize for specific integer values.
[Example:—end example]
template< unsigned number> class I { void print(){ std::cout << "Primary template." << std::endl; } }; template< > class I< 0 > { void print(){ std::cout << " up to 10 and 10 ." << std::endl; } }; /* In here repeat above code with numbers between 1 and 10*/ template< > class I< 10 > { void print(){ std::cout << " up to 10 and 10." << std::endl; } }; template< > class I< 11 > { void print(){ std::cout << " up to 100 and 100." << std::endl; } }; /* repeat above code with numbers between 11 and 100*/ template< > class I< 100 > { void print(){ std::cout << " up to 100 and 100." << std::endl; } };
III. Solutions
- Solutions within current standard
- Using copy/paste
- Already demonstrated in above examples. Lacks are obvious and well known.
- By using macro replacement (
#define
).
[Example:—end example] Replacing template with
template< typename T > class A { void print(){ std::cout << "Primary template" << std::endl; } }; #define A_for_string(string_like_type) \ template< > \ class A< string_like_type T > { \ void print(){ std::cout << "String template" << std::endl; } \ } A_for_string( char* ); A_for_string( std::string ); A_for_string( std::wsring );#define
is bad idea. And again lacks are obvious and well known.- Involving the inheritance
[Example:—end example]
template< typename T > class A { void print(){ std::cout << "Primary template" << std::endl; } }; template< typename string_like_type > class A_string { void print(){ std::cout << "String template" << std::endl; } } template<> class A< std::string > : public A_string< std::string > { // nothing }; template<> class A< std::wstring > : public A_string< std::wstring > { // nothing };
In this case there is additional class that need to bi hidden from user. This can be consider as code bloat.- Proposal
- Use list of types in place on one type. Type list should be enclosed with '{' and '}'.
All examples can be easily extended in partial specialization examples.
- float, string, ints:
- Generalized primary template. Several specialized templates at once with list of types
[Example:—end example]
template< typename T > // Primary template. As per standard class A { void print(){ std::cout << "Primary template" << std::endl; } }; template<> class A< { char*, std::string, std::wstring } > { // Instead one type it is list of types. void print(){ std::cout << "String specialization" << std::endl; } }; template<> class A< { float, double, long double } > { void print(){ std::cout << "Rational specialization" << std::endl; } }; template< typename T > class A< std::vector < { T, short, int, long } > > { // Partial and and full specialization at once. void print(){ std::cout << "std::vector < Integers >" << std::endl; } };- enums:
- Primary template with default parameter and two more types ( actually enums ).
Enums must appear in ascending order.
[Example:—end example]
enum colors{ red, green, blue, cyan, yellow, magenta, orange, pink }; // red is default, Other enums in list must appear in order of appearance in their definition. template< enum Colors color = red { red, ... , blue } > class E { void print(){ std::cout << "Primary template with red default"<< std::endl; } }; template< > class E< { cyan, ... , yellow } > { // Take all enums between cyan and key // Brand new specialization of print function void print(){ std::cout << "YELLOW"<< std::endl; } };- Integer:
- Demonstration of massive specialization on very small space.
Only integral types can use ellipsis.
Numbers must appear in ascending order.
[Example:—end example]
template< unsigned number = 0 > class I { void print(){ std::cout << "Primary template." << std::endl; } }; template< > class I< { 1, ..., 10 } >{ // Numbers must appear in increasing order void print(){ std::cout << " up to 10 and 10 ." << std::endl; } }; template< > class I< { 11, ..., 100 } > { void print(){ std::cout << " from 11 to 100 and 100." << std::endl; } }; template< > class I< 42 >{ // ERROR: Already specialized. { void print(){ std::cout << " 42." << std::endl; } };- Multi specialization on two ( or more ) parameters:
- When two or more parameters are list of types ( or integers ) all pairs ( tuples ) will be specialized.
[Example:—end example]
template< typename S, typename T > class D { void print(){ std::cout << "Primary template." << std::endl; } }; template< > class D< { int, long }, { std::string, std::wstring } >{ void print(){ std::cout << "{ int, long }, { std::string, std::wstring }" << std::endl; } }; template< > class D< int, std::wstring >{ // ERROR: Specialization already exists void print(){ std::cout << " int, std::wstring " << std::endl; } };
It is not possible to have some exception for some pair ( tuples ) of types.
[Example:—end example]
template< typename S, typename T > class E { void print(){ std::cout << "Primary template." << std::endl; } }; template< > class E< int, std::wstring >{ // OK. Specialization for int and std::wstring void print(){ std::cout << " int, std::wstring " << std::endl; } }; template< > class E< { int, long }, { std::string, std::wstring } >{ // ERROR: One pair is already specialized. void print(){ std::cout << "{ int, long }, { std::string, std::wstring }" << std::endl; } }; IV. Design Decisions
- Massive (partial)specialization at the cost of one definition.
- Due to fact the that same code are shared with other types it is not possible make different implementation mistakenly for some type of same group.
- There is no need for additional code like in N3596 or similar solution. Which is one of the main goal i.e no additional code. One place and start place only.
- Do not solve (and not intention): Reuse of existing (partial)specialization by modification, function/member excluding/adding/redefining.
V. Impact On the Standard
Core- No effect.
No new keywords.
No new tokens.
No changes to old syntax.
Pure extension.
Backward compatible. Library- No effect.
No new class.
No new functions. Existing code.- No effect.
> This language feature is called Concepts, and is already in the working draft for C++20Concept allows you to make constraints on not (yet) exiting types.This make specialization on existing types.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAEfefmy8ApLMd3Ano1jowNWZoqqteass%2BxAP2a4wjR7uhUvFuw%40mail.gmail.com.
> This language feature is called Concepts, and is already in the working draft for C++20Concept allows you to make constraints on not (yet) exiting types.This make specialization on existing types.
is_any_of_v technique. While your idea is interesting, we already have a much superior feature already voted in C++20, so I'm afraid we don't need yours.
A.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/66132261-3dde-49ec-a62c-ac4330815621%40isocpp.org.
For concepts there is need for concept which require pile of code to write/read/maintain.
Second example also add descent amount of code too and for the first read can be confusing for understanding.
Mainly we want to read code just once line by line, without scrolling up/down to see more code to understand our current focus.This proposal shrink this to minimal.One line to write. One line to read. One line to maintain.
Il giorno mercoledì 21 marzo 2018 09:55:54 UTC+1, Dejan Milosavljevic ha scritto:For concepts there is need for concept which require pile of code to write/read/maintain.
What? As long as the standard library includes a facility like is_any_of_v (and I'm sure that's going to happen), you don't need to write more than one extra line. I don't see a big difference between
template <typename T>
requires is_any_of_v<T, char*, std::string, std::wstring>
class A<T> { ... };
and
template<>
class A< { char*, std::string, std::wstring } > { ... };
in terms of maintainability.
Second example also add descent amount of code too and for the first read can be confusing for understanding.
What second example? Please be more specific.
Mainly we want to read code just once line by line, without scrolling up/down to see more code to understand our current focus.This proposal shrink this to minimal.One line to write. One line to read. One line to maintain.
One more feature to learn, that is useful only in this specific case.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d1f5be50-77f6-45cc-875a-d084d55e8b60%40isocpp.org.