模板参数类型转换无效?



在这个问题的帮助下,我逐渐构建了这段代码,这是一个类成员函数的包装器。这个想法是,我可以在我的属性上使用操作符*来写入类对象:

#include <cstdio>
#include <type_traits>
#include <utility>
using namespace std;

class testclass {
public:
double get() { return d_; }
bool set(double d) { d_ = d; return true; }
double d_ = 0.0;
};
template <typename PropertyType>
struct DEFAULT_WRAPPER_PROXY {
DEFAULT_WRAPPER_PROXY(PropertyType* p) : property_(p) {}
operator typename PropertyType::GetterReturnType() {
return property_->Get();
}
DEFAULT_WRAPPER_PROXY& operator=(typename PropertyType::GetterReturnType val) {
property_->Set(val);
return *this;
}
PropertyType* property_;
};
template <typename PropertyType>
struct LOGGING_WRAPPER_PROXY {
LOGGING_WRAPPER_PROXY(PropertyType* p) : property_(p) {}
operator typename PropertyType::GetterReturnType() {
// Log some interesting stuff
return property_->Get();
}
LOGGING_WRAPPER_PROXY& operator=(typename PropertyType::GetterReturnType val) {
// Log some interesting stuff
property_->Set(val);
return *this;
}
PropertyType* property_;
};
template<typename Retriever, typename Updater, typename OwningClass, template<typename PropertyType> class WRAPPER_PROXY = DEFAULT_WRAPPER_PROXY>
struct Wrapper {
Wrapper(Retriever retriever, Updater updater, OwningClass* owner) : retriever_(retriever), updater_(updater), containingClass_(owner) {}
using GetterReturnType = std::invoke_result_t<Retriever, OwningClass>;
GetterReturnType Get() { return (containingClass_->*retriever_)(); }
template<typename...Args>
using SetterReturnType = std::invoke_result_t<Updater, OwningClass, Args...>;
template<typename...Args>
SetterReturnType<Args...> Set(Args&&... args) { return (containingClass_->*updater_)((forward<Args>(args))...); }
WRAPPER_PROXY<Wrapper<Retriever, Updater, OwningClass>> operator*() {
return  WRAPPER_PROXY(this);
}
Retriever retriever_;
Updater updater_;
OwningClass* containingClass_;
};
template<
template<typename PropertyType>
class WRAPPER_PROXY,
typename Retriever,
typename Updater,
typename OwningClass>
auto MakeWrapper(Retriever&& retriever, Updater&& updater, OwningClass* const owner) {
return Wrapper<Retriever, Updater, OwningClass, WRAPPER_PROXY>(
std::forward<Retriever>(retriever),
std::forward<Updater>(updater),
owner
);
}
int main() {
testclass tc;
// Cleaner (using CTAD here, could also use auto)
Wrapper pp3 = MakeWrapper<LOGGING_WRAPPER_PROXY>(
&testclass::get,
&testclass::set,
&tc
);
*pp3 = 100;
Wrapper pp4 = MakeWrapper<DEFAULT_WRAPPER_PROXY>(
&testclass::get,
&testclass::set,
&tc
);
*pp4 = 100;
}

不能在*pp3 = 100上编译,因为VS2022状态为

cannot convert from 'LOGGING_WRAPPER_PROXY<Wrapper<double (__cdecl testclass::* )(void),bool (__cdecl testclass::* )(double),testclass,LOGGING_WRAPPER_PROXY>>' 
to 'LOGGING_WRAPPER_PROXY<Wrapper<Retriever,Updater,OwningClass,DEFAULT_WRAPPER_PROXY>>'

with
[
Retriever=double (__cdecl testclass::* )(void),
Updater=bool (__cdecl testclass::* )(double),
OwningClass=testclass
]

我不明白为什么它试图创建一个DEFAULT_WRAPPER_PROXY,这里出了什么问题?

问题原因:
struct Wrapper是一个具有4个模板形参的结构体,其中最后一个模板形参具有默认值:

template<typename Retriever, 
typename Updater, 
typename OwningClass, 
template<typename PropertyType> class WRAPPER_PROXY = DEFAULT_WRAPPER_PROXY>
struct Wrapper { /* ... */ }

struct Wrapper的这一行:

WRAPPER_PROXY<Wrapper<Retriever, Updater, OwningClass>> operator*() {

您没有指定Wrapper的最后一个模板参数,因此默认ofDEFAULT_WRAPPER_PROXY使用。
当试图使用operator*,结果为MakeWrapper<LOGGING_WRAPPER_PROXY>时,将导致编译错误.

解决方案:
您可以像下面所示那样通过显式地添加最后一个模板参数来修复它:

//-----------------------------------------------------vvvvvvvvvvvvv
WRAPPER_PROXY<Wrapper<Retriever, Updater, OwningClass, WRAPPER_PROXY>> operator*() {

相关内容

  • 没有找到相关文章

最新更新