Ошибка в VS2013 при попытке частично специализировать шаблон класса с другим шаблоном класса

0

Учитывая следующие шаблоны классов и функций:

template <typename WrappedType, ParameterType ParamType, bool IsOutputParameter>
    class WrappedParameter; // Definition left out for brevity

template <typename T>
struct ParameterUnwrapper
{
    static T UnwrapParameter(const T& in_param)
    {
        return in_param;
    }
};

template <typename T, ParameterType ParamType, bool IsOutputParameter>
struct ParameterUnwrapper<WrappedParameter<T, ParamType, IsOutputParameter>>
{
    static T UnwrapParameter(const WrappedParameter<T, ParamType, IsOutputParameter>& in_param)
    {
        return in_param.GetWrapped();
    }
};

template <typename T>
T UnwrapParameter(T in_param)
{
    return Impl::ParameterUnwrapper<T>::UnwrapParameter(in_param);
}

template <typename T>
Impl::WrappedParameter<T, Impl::POINTER_PARAMETER, true> WrapOutputPointerParameter(T in_param)
{
    return Impl::WrappedParameter<T, Impl::POINTER_PARAMETER, true>(in_param);
}

template <typename MemFunc, typename ...Args>
HRESULT ExecuteAndLog(
    MemFunc in_memberFunction,
    const std::string& in_methodName,
    Args... args) //-> decltype((m_wrapped->*in_memberFunction)(UnwrapParameter(args)...))
{
    return ExecuteFunctorAndLog(
        [&]() { return (m_wrapped->*in_memberFunction)(UnwrapParameter(args)...); },
        in_methodName,
        args...);
}

Следующий вызов: (ExecuteAndLog)

HRESULT STDMETHODCALLTYPE AccessorWrapper::AddRefAccessor(
    HACCESSOR hAccessor,
    DBREFCOUNT *pcRefCount)
{
    return ExecuteAndLog(
        &IAccessor::AddRefAccessor,
        "AddRefAccessor",
        hAccessor,
        WrapOutputPointerParameter(pcRefCount));
}

Дает мне ошибки:

error C2664: 'HRESULT (HACCESSOR,DBREFCOUNT *)' : cannot convert argument 2 from 'Impl::WrappedParameter<DBREFCOUNT *,POINTER_PARAMETER,true>' to 'DBREFCOUNT *'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
see reference to function template instantiation 'ExecuteAndLog<HRESULT(__stdcall IAccessor::* )(HACCESSOR,DBREFCOUNT *),HACCESSOR, Impl::WrappedParameter<DBREFCOUNT *,POINTER_PARAMETER,true>>(MemFunc,const std::string &,HACCESSOR,Impl::WrappedParameter<DBREFCOUNT *,POINTER_PARAMETER,true>)' being compiled
with
[
    MemFunc=HRESULT (__stdcall IAccessor::* )(HACCESSOR,DBREFCOUNT *)
]
see reference to function template instantiation 'ExecuteAndLog<HRESULT(__stdcall IAccessor::* )(HACCESSOR,DBREFCOUNT *),HACCESSOR,Impl::WrappedParameter<DBREFCOUNT *,POINTER_PARAMETER,true>>(MemFunc,const std::string &,HACCESSOR,Impl::WrappedParameter<DBREFCOUNT *,POINTER_PARAMETER,true>)' being compiled
with
[
    MemFunc=HRESULT (__stdcall IAccessor::* )(HACCESSOR,DBREFCOUNT *)
]

Я думаю, что я испортил частичную специализацию ParameterUnwrapper (или мой подход просто неверен). Любой совет?

Больше информации:

Impl - это вложенное пространство имен (наряду с пространством имен все предоставленные шаблоны, за исключением ExecuteAndLog)

В этом случае m_wrapped имеет тип IAccessor * (интерфейс COM).

        enum ParameterType
        {
            POINTER_PARAMETER,

            ARRAY_PARAMETER
        };

ОБНОВЛЕНИЕ: Здесь приведен пример: http://codepad.org/lwTzVImb

Ошибка, которую я получаю в VS2013 для этого:

error C2664: 'int (int,int **,size_t *)' : cannot convert argument 2 from 'WrappedParameter<int **,ARRAY_PARAMETER,true>' to 'int **'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
see reference to function template instantiation 'int ExecuteAndLog<int(__thiscall A::* )(int,int **,size_t *),int,WrappedParameter<int **,ARRAY_PARAMETER,true>,size_t*>(MemFunc,const std::string &,int,WrappedParameter<int **,ARRAY_PARAMETER,true>,size_t *)' being compiled
with
[
    MemFunc=int (__thiscall A::* )(int,int **,size_t *)
]
  • 1
    Вам не хватает определений для ParameterType , POINTER_PARAMETER m_wrapped и Impl . Было бы очень полезно, если бы вы опубликовали что-то, что кто-то другой может скомпилировать, чтобы увидеть ту же ошибку. Я попытался придумать свои собственные определения для них, чтобы скомпилировать ваш код, и я получил ту же ошибку, о которой вы сообщили, но я исправил ее, изменив то, что я определил как POINTER_PARAMETER . (Сначала у меня был тип, отличный от ParameterType, затем я сделал то же самое).
  • 0
    Ваш код еще далек от того, чтобы быть MCVE . Я составил материал, для которого вы опускали определения, и он хорошо компилируется с вызовом функции . Будет лучше, если вы сможете опубликовать MCVE, чтобы показать проблему, с которой вы столкнулись, поскольку «реальный код», несомненно, отличается от того, что я должен был угадать.
Показать ещё 3 комментария
Теги:
templates
visual-studio-2013
template-specialization

1 ответ

1
Лучший ответ

Я понял!

Проблема заключалась в обратном типе UnwrapParameter. Как только я изменил объявление

    template <typename T>
    auto UnwrapParameter(T in_param) -> decltype(Impl::ParameterUnwrapper<T>::UnwrapParameter(in_param))

Он скомпилирован. Стыдно, что компилятор не жаловался на определение этой функции, а не доверял ее объявленному возвращаемому значению.

У меня есть некоторые другие проблемы прямо сейчас, но, по крайней мере, я добился прогресса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню