问题
I am trying to build a specialization for a template class with a compile time constant.
The template class looks like this:
template<class TNativeItem, class TComItem = void,
VARTYPE _vartype = _ATL_AutomationType<TComItem>::type>
class InOutComArray
{
private:
CComSafeArray<TComItem, _vartype> _safeArray;
// ...
public:
InOutComArray(
TNativeItem* items, size_t length,
std::function<TComItem(const TNativeItem&)> convertToCom,
std::function<TNativeItem(const TComItem&)> convertFromCom)
: _safeArray(length)
{
// ...
}
// ...
};
Usage would be for example:
InOutComArray<BOOL, VARIANT_BOOL, VT_BOOL>(
items, length, BOOLToVARIANT_BOOL, VARIANT_BOOLToBOOL));
However, there also exist types that don't require conversion and I wanted to provide a short hand version for this:
InOutComArray<LONG>(items, length);
I tried to implement it like this:
template<class TItem, VARTYPE _vartype = _ATL_AutomationType<TItem>::type>
class InOutComArray<TItem, void, _vartype>
: public InOutComArray<TItem, TItem, _vartype>
{
public:
InOutComArray(TItem* items, size_t length)
: InOutComArray<TItem, TItem, _vartype>(
items, length, NoConverter<TItem>, NoConverter<TItem>)
{
}
};
However, I get the following error:
'_vartype' : default template arguments not allowed on a partial specialization
Is there any way around that?
回答1:
You first define the default arguments to be void
and _ATL_AutomationType<TComItem>::type
, so when exactly one argument X is given, you want InOutComArray<X>
to be an InOutComArray<X, void, _ATL_AutomationType<void>::type>
.
Your partial specialization contradicts this: InOutComArray<X>
shall be a InOutComArray<X, X, _ATL_AutomationType<X>::type>
.
Depending on what you thik will be more likely second argument, (i.e. void
or the same as the first argument), you could make the second argument defaulted to the first one in the first place:
template<class TNativeItem, class TComItem = TNativeItem,
VARTYPE _vartype = _ATL_AutomationType<TComItem>::type>
That way the behavior of the partial specialization is covered, except for the additional constructor. This can be achieved by using default arguments for the constructor:
template<class TNativeItem, class TComItem = TNativeItem,
VARTYPE _vartype = _ATL_AutomationType<TComItem>::type>
class InOutComArray
{
public:
InOutComArray(
TNativeItem* items, size_t length,
std::function<TComItem(const TNativeItem&)> convertToCom = NoConverter<TNativeItem>(),
std::function<TNativeItem(const TComItem&)> convertFromCom = NoConverter<TNativeItem>());
};
回答2:
According to the standard §14.5.5/8 Class template partial specializations [temp.class.spec]:
The template parameter list of a specialization shall not contain default template argument values.
Thus, the compiler rightfully complains because in your partial specialization you give default template argument value for VARTYPE _vartype = _ATL_AutomationType<TItem>::type
.
回答3:
Is there any way around that?
Yes, remove the default template argument from the partial specialization. You don't need it.
Per the primary template:
template<class TNativeItem, class TComItem = void,
VARTYPE _vartype = _ATL_AutomationType<TComItem>::type>
class InOutComArray
These types are equivalent:
InOutComArray<LONG>
InOutComArray<LONG, void, _ATL_AutomationType<TComItem>::type>
And whenever InOutComArray
is instantiated with TComItem = void
, you will get the partial specialization:
template<class TItem, VARTYPE _vartype>
class InOutComArray<TItem, void, _vartype>
来源:https://stackoverflow.com/questions/25362727/template-specialization-with-compile-time-constant