Template specialization with compile time constant

左心房为你撑大大i 提交于 2021-01-29 02:21:46

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!