Skip to search.
boost · C++ Boost

Group Information

  • Members: 4382
  • Category: C and C++
  • Founded: Oct 23, 1998
  • Language: English
? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Hear how Yahoo! Groups has changed the lives of others. Take me there.

Messages

  Messages Help
Advanced
Simulating Partial Specialization   Message List  
Reply Message #5441 of 27136 |

Colleagues:

Today much of the current C++ literature laments the lack of
widespread compiler support for partial template specialization.
There are some well known workarounds, but they tend to be of limited
applicability. We are currently employing a "simulated partial
specialization" technique that applies to a broader range of
problems. In particular allows specialization of template classes for
pointer types. One interesting application is to allow improved STL
implementations on non-compliant compilers. The following code was
tested on Microsoft Visual C++ 6 service pack 3. In this toy example
we present a simple vector class which is specialized for pointer
types. The template metaprogramming techniques used support
simulation of other partial specialization features, e.g. holding one
or more template parameters fixed, as well as a kind of poor man's
typeof. We have enjoyed some success applying these techniques to a
larger STL-style generic container library.

Here is an outline of the idea. We make use of the IF template
metafunction (or SWITCH if there is more than one specialization)
and the sizeof operator.

IF --- IF is actually a template struct based on a bool and two type
parameters - IF<bool, IfType, ElseType>. It 'returns' the
appropriate type via the RET typedef where RET stands for return.

sizeof --- we recently learned of the flexibility of the sizeof
operator.In particular sizeof can accept a function expression
without evaluating the function. We declare (but do not define) a
pair of discriminating functions to determine if a specialization
applies. In the case of pointers we (essentially) use

char IsPtr(const volatile void*);
int IsPtr(...);

We convert this pair of discriminating functions into a template
metafunction ISPTR<T>. That is, ISPTR <T> returns true in the RET
enum if and only if T is a pointer type. Finally this allows us to
write IF<ISPTR<T>::RET, PointerSpecialized<T>,
Unspecialized<T> >::RET to achieve simulated partial specialization
where PointerSpecialized is the specialized version of the type and
Unspecialized is the general case. By varying these discriminators we
can specialize on other criteria.

As stated above we can generalize this technique using the SWITCH
metafunction and more than two discriminating functions. For example
we might define a discriminating metafunction SPECIALIZER which
returns an int rather than a bool. Than the simulated specialization
would look like

SWITCH<SPECIALIZER<T>,
CASE<1, FIRST_SPECIALIZATION<T>,
CASE<2, SECOND_SPECIALIZATION<T>,
CASE<DEFAULT, GENERAL_CASE<T> >::RET

Needless to say it is possible to discriminate on more than one
template parameter.

Hope you find this useful,

Mat Marcus - mmarcus@...
Jesse Jones - jejones@...

References:
Thanks to Krzysztof Czarnecki & Ulrich Eisenecker for the
metaprogramming skills from the book Generative Programming. Thanks
to Scott Meyers and Andrei Alexandrescu for the posts regarding the
utility of the sizeof operator. Thanks to John R. Bandela for making
us consider whether there might be some portable way to simulate
partial specialization.

License: The Adobe source code below is provided under the Adobe Open
Source License 1.0. Please see file AdobeLicense.txt for licensing
information.




//##################################################################
// File: PartialSpecialization.cpp
// Authors: Mat Marcus and Jesse Jones
// Copyright 2000 Adobe Systems Incorporated and others. All rights reserved.
// The original version of this source code may be found at
http://opensource.adobe.com.
// The contents of this file are subject to the Adobe Open Source
// License Version 1.0.

#include <iostream>
#include <string>
#include "metactrl.h" // General template meta-functions
#include "is_ptr.h" // IsPtr template meta-function


template <class T>
struct SimpleVector {
// Simple example vector class. We omit almost all implementation.
friend std::ostream& operator<<(std::ostream& out, const SimpleVector<T>&)
{
return out << "is a simple vector";
}
};

template <class T>
struct PtrVector {
// Simple example vector of pointers class. We omit almost all
implementation.
friend std::ostream& operator<<(std::ostream& out, const PtrVector<T>&)
{
return out << "is a pointer vector";
}


};

template <class T>
struct SELECT_VECTOR {
// The SELECT_VECTOR meta-function exists simply to make
// the following code more readable.
typedef typename metactrl::IF<metactrl::ISPTR<T>::RET,
PtrVector<T>,
SimpleVector<T>
>::RET Vector;
};

/* The heart of the matter. The meta-function metactrl::IF takes a boolean
and returns the second type parameter if true else the third. This is a
useful tool in template metaprogramming (see metactrl.h for details).
The meta-function metactrl::ISPTR makes use of the sizeof operator to
convert a type into a bool indicating whether or not it is a pointer.
See is_ptr.h for details.
*/

template <class T>
struct Vector : public SELECT_VECTOR<T>::Vector {
// One way to achieve a general Vector class is to inherit from the
// appropriate specialization. Clients can simply use Vector<T> and
// we will specialize accordingly. However this inheritance based
// wrapper approach has some limitations.
};




// We illustrate two approaches to simulated partial specialization

int main(int argc, char* argv[])
{
// Example 1 using the inheritance based wrapper approach
Vector<int> vi;
std::cout << "Vector of int " << vi << std::endl;
//Output: Vector of int is a simple vector

Vector<int*> vip;
std::cout << "Vector of int* " << vip << std::endl;
//Output: Vector of int* is a pointer vector


// Example 2 using the direct approach
SELECT_VECTOR<std::string>::Vector ds;
std::cout << "Vector of string " << ds << std::endl;
//Output: Vector of string is a simple vector

SELECT_VECTOR<std::string*>:: Vector dsp;
std::cout << "Vector of string* " << dsp << std::endl;
//Output: Vector of string* is a pointer vector

return 0;
}


//##################################################################

// File: is_ptr.h
// Authors: Mat Marcus and Jesse Jones
// Copyright 2000 Adobe Systems Incorporated and others. All rights reserved.
// The original version of this source code may be found at
http://opensource.adobe.com.
// The contents of this file are subject to the Adobe Open Source
// License Version 1.0.

namespace metactrl {
namespace intimate {
struct PointerShim {
// Since the compiler only allows at most one non-trivial
// implicit conversion we can make use of a shim class to
// be sure that IsPtr below doesn't accept classes with
// implicit pointer conversion operators
PointerShim(const volatile void*); // no implementation
};

// These are the discriminating functions
char IsPtr(PointerShim); // no implementation is required
int IsPtr(...); // no implementation is required
}

template <class T>
struct ISPTR {
// This template meta function takes a type T
// and returns true exactly when T is a pointer.
// One can imagine meta-functions discriminating on
// other criteria.

enum { RET = (sizeof(intimate::IsPtr(*(T*)0)) == 1) };
};
}

//##################################################################

// File: metactrl.h
// Authors: Krzysztof Czarnecki & Ulrich Eisenecker
// We present only a small subset here

/* The following functions come from chapter 10 of the indispensable book
Generative Programming by Krzysztof Czarnecki & Ulrich Eisenecker
(C) Copyright Krzysztof Czarnecki & Ulrich Eisenecker 1998-2000.
Permission to copy, use, modify, sell and distribute this software is
granted provided this copyright notice appears in all copies. In case of
modification, the modified files should carry a notice stating that
you changed the files.
This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
*/
namespace metactrl
{

// IF<> // version for compilers without partial specialization

namespace intimate
{
struct SelectThen
{ template<class Then, class Else>
struct Result
{ typedef Then RET;
};
}; // end SelectThen

struct SelectElse
{ template<class Then, class Else>
struct Result
{ typedef Else RET;
};
}; // end SelectElse

template<bool Condition>
struct Selector
{ typedef SelectThen RET;
}; // end Selector

template<>
struct Selector<false>
{ typedef SelectElse RET;
}; // end Selector<false>
} // end namespace intimate

template<bool Condition, class Then, class Else>
struct IF
{ typedef intimate::Selector<Condition>::RET select;
typedef select::Result<Then,Else>::RET RET;
}; // IF
} // end namespace metactrl


// CASE<>, SWITCH<> // version for compilers without partial specialization

const int DEFAULT = -32767;

namespace intimate
{
const int NilValue = -32768;

struct NilCase
{ enum {tag = NilValue};
typedef NilCase RET;
}; // NilCase
} // end namespace intimate;

template <int Tag,class Statement,class Next = intimate::NilCase>
struct CASE
{ enum {tag = Tag};
typedef Statement statement;
typedef Next next;
}; // CASE

template <int Tag,class aCase>
struct SWITCH
{ typedef aCase::next nextCase;
enum { tag = aCase::tag, // VC++ 5.0 doesn't operate directly on
aCase::value in IF<>
nextTag = nextCase::tag,// Thus we need a little cheat
found = (tag == Tag || tag == DEFAULT)
};
typedef IF<(nextTag == intimate::NilValue),
intimate::NilCase,
SWITCH<Tag,nextCase> >
::RET nextSwitch;
typedef IF<(found != 0),
aCase::statement,
nextSwitch::RET>
::RET RET;
}; // SWITCH

//#########################################
//file: AdobeLicense.txt

Notice to User: Adobe Systems Incorporated ("Adobe") is providing the
source code in these documents for use under the terms of this Adobe
Open Source License Agreement ("Agreement"). Any use, reproduction,
modification, or distribution of the source code, resulting object
code, or related documentation on this site, or any derivatives
thereof (collectively, the "Software") constitutes your acceptance of
this Agreement. Adobe reserves the right to make changes to this
Agreement from time to time at its sole discretion. The version of
this Agreement posted on the date you download the Software will
apply to that version of the Software.
1. License Grant
Subject to the terms of this Agreement, Adobe grants you a
non-exclusive, worldwide, royalty free license to use, reproduce,
prepare derivative works, publicly display, publicly perform,
distribute, and sublicense the Software for any purpose, provided the
copyright notice below, appears in a conspicuous location within the
source code of the distributed Software and this license is
distributed with the version of the Software you distribute in the
supporting documentation.
Copyright (Date Here) Adobe Systems Incorporated and others.
All rights reserved.
The original version of this source code may be found at
http://opensource.adobe.com.

If you choose to distribute the Software in a commercial product, you
do so with the understanding that you agree to defend, indemnify, and
hold harmless Adobe against any losses, damages, and costs, arising
from the claims, lawsuits, and other legal actions, arising out of
such distribution. You may distribute the Software in object code
form under your own license, provided that your license agreement:
(a) complies with the terms and conditions of this license agreement;
(b) effectively disclaims all warranties and conditions, express
or implied, on behalf of Adobe;
(c) effectively excludes all liability for damages, on behalf of Adobe;
(d) states that any provisions that differ from this Agreement
are offered by you alone and not Adobe; and
(e) states that the Software covered by this Agreement is
available from you or Adobe and informs licenses how to obtain it in
a reasonable manner on or through a medium customarily used for
software exchange.
2. Disclaimer of Warranty
ADOBE LICENSES THE SOFTWARE TO YOU ONLY ON AN "AS IS" BASIS WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
INCLUDING WITHOUT LIMITATION ANY WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE. ADOBE MAKES NO WARRANTY THAT THE SOFTWARE WILL BE
ERROR-FREE. Each user of the Software is solely responsible for
determining the appropriateness of using and distributing the
Software and assumes all risks associated with its exercise of rights
under this Agreement, including but not limited to the risks and
costs of program errors, compliance with applicable laws, damage to
or loss of data, programs, or equipment, and unavailability or
interruption of operations. Use of the Software is done so with the
understanding that Adobe will not provide you with any technical or
customer support or maintenance. Some states or jurisdictions do not
allow the exclusion of implied warranties or limitations on how long
an implied warranty may last, so the above limitations may not apply
to you. To the extent permissible, any implied warranties are limited
to ninety (90) days.
3. Limitation of Liability
ADOBE SHALL NOT BE LIABLE FOR LOSS OR DAMAGE ARISING OUT OF THIS
AGREEMENT OR FROM THE USE OF THE SOFTWARE. IN NO EVENT WILL ADOBE BE
LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT,
CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES INCLUDING LOST PROFITS,
LOST SAVINGS, COSTS, FEES, OR EXPENSES OF ANY KIND ARISING OUT OF ANY
PROVISION OF THIS AGREEMENT OR THE USE OR THE INABILITY TO USE THE
SOFTWARE, HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
4. Trademark Usage
Adobe is a trademark or registered trademark of Adobe Systems
Incorporated in the United States and/or other countries. Neither the
Adobe name nor the Adobe logo may be used to endorse or promote
products derived from this site.
5. Termination
User rights shall terminate under this Agreement if the user fails to
comply with any of the material terms or conditions of this Agreement
and does not cure such failure in a reasonable period of time after
becoming aware of such noncompliance. If all user's rights under this
Agreement terminate, user agrees to cease use and distribution of the
Software as soon as reasonably practicable.
6. Governing Law and Jurisdiction
This Agreement is governed by the statutes and laws of the State of
California, without regard to the conflicts of law principles
thereof. If any part of this Agreement is found void and
unenforceable, it will not affect the validity of the balance of the
Agreement, which shall remain valid and enforceable according to its
terms. This is the entire agreement between Adobe and you relating to
the Software.



Fri Sep 29, 2000 10:03 pm

mmarcus@...
Send Email Send Email

Message #5441 of 27136 |
Expand Messages Author Sort by Date

Colleagues: Today much of the current C++ literature laments the lack of widespread compiler support for partial template specialization. There are some well...
Mat Marcus
mmarcus@... Send Email
Sep 29, 2000
9:58 pm

While this technique doesn't allow users to graft on their own specializations for various types, it seems like it will allow us to work around the limitation...
David Abrahams
abrahams@... Send Email
Sep 29, 2000
11:19 pm

... Looks like someone else has been experimenting with this, I've been trying to improve the quality of type-traits support for VC6, with the hope of getting...
John Maddock
John_Maddock@... Send Email
Sep 30, 2000
12:23 pm

... From: "John Maddock" <John_Maddock@...> ... happy ... If you have some way of determining whether an expression is a compile-time constant, I...
David Abrahams
abrahams@... Send Email
Sep 30, 2000
12:36 pm

... That doesn't help, however I think I have an alternative anyway... ... Yes they should, but I can't get VC6's overload resolution working correctly here...
John Maddock
John_Maddock@... Send Email
Oct 1, 2000
11:55 am

From: "John Maddock" <John_Maddock@...> ... I'm shocked! And pleased! ... I'm shocked and dismayed, given that those posts were directly addressing ...
David Abrahams
abrahams@... Send Email
Oct 1, 2000
1:32 pm

Anybody have any ideas of how to use this technique to implement iterator_traits in the STL? This technique allows differentiation between user defined...
jbandela@... Send Email Oct 2, 2000
12:09 am

Looks like ISPTR used as a discriminator for full class specialization will work if ISCONST used as a secondary discriminator and member template classes work...
Boris Fomitchev
fbp@... Send Email
Oct 2, 2000
3:46 pm

Forgive me if I am misunderstanding your post, but if Iterator is a pointer, Iterator::value_type won't be defined. John Bandela ... have ... typedefs...
jbandela@... Send Email Oct 2, 2000
5:21 pm

... It looks like you have rediscovered the metactrl::IF technique. However the problem of determining the underlying type from a pointer template parameter at...
Mat Marcus
mmarcus@... Send Email
Oct 2, 2000
5:54 pm

Hi, I don't know if you already have a ISPTR, but this works fine for me on MSVC6SP3. Best regards, Sofus Mortensen tlb2h - A COM/C++ interoperability tool ...
Sofus Mortensen
sofus@... Send Email
Oct 2, 2000
7:27 pm

Well, in fact I did know about IF technique, just elaborated it a bit here. So we do not have any remove_const<> solutions w/o partial specialization ? That's...
Boris Fomitchev
fbp@... Send Email
Oct 3, 2000
5:06 am

... is_same is fairly straightforward using the "pointer trick" below. is_ref had eluded us until David's post: ... Au contraire. I believe this is a key...
Mat Marcus
mmarcus@... Send Email
Oct 2, 2000
10:39 am

... From: "Mat Marcus" <mmarcus@...> ... trick ... I don't think this will work. And VC6.3 bears me out: char IsNonConstPointer(void*); int...
David Abrahams
abrahams@... Send Email
Oct 2, 2000
11:43 am

... Monday morning, back at my Windows box. The above code seems to work for me on VC6.3 after correcting some typos: template <class T> struct ISCONST { enum...
Mat Marcus
mmarcus@... Send Email
Oct 2, 2000
5:46 pm

(Sorry to leave so much of the original messages in this post, but everything seems important to quote.) ... hadn't ... That is ... The pointer ... == 1)}; ......
William Kempf
sirwillard@... Send Email
Oct 2, 2000
7:40 pm

... Sorry. What I meant to type was ... template <class T> struct ISREF { // doesn't work :-( enum {RET = (1 != sizeof(IsNonConstPointer(&(( (Holder<T>*)...
Mat Marcus
mmarcus@... Send Email
Oct 2, 2000
11:07 pm
Advanced

Copyright © 2010 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines NEW - Help