我写了以下函数:
template< class C, typename T, typename U >
void addVarCB(C * _this, const std::string &name,
T(C::*getter)(void) const, U(C::*setter)(const T&), const std::string &def);
然后我意识到如果setter将T作为输入,它就不会工作,所以我重载了函数:
template< class C, typename T, typename U >
void addVarCB(C * _this, const std::string &name,
T(C::*getter)(void) const, U(C::*setter)(T), const std::string &def = "");
现在我意识到如果getter返回
,即使这样也会失败const T &
T &
const T *
T *
const T // yeah this is dumb but someone on my team wrote code like this...
我注定要在整个地方复制相同的代码吗? 希望至少解决方案仅适用于参考版本?
请注意,该函数将this指针指向一个对象,一个getter和一个setter公共成员函数。 然后,该函数将与GUI连接,允许稍后调用getter和setter。
答案 0 :(得分:2)
某些模板元编程可以解决您的问题:(以下需要C ++ 11,但使用boost可以实现相同的目标)
#include<string>
#include<type_traits>
template<typename T>
struct BaseType {
typedef typename std::remove_const<typename std::remove_reference<T>::type>::type type;
};
struct MyClass{
int a;
std::string s;
const int & getA() const {return a;}
void setA(int a) {this->a=a;}
std::string getS() const {return s;}
};
template< class C, typename Tget, typename Tset, typename U,
class = typename std::enable_if<
std::is_same<
typename BaseType<Tget>::type,
typename BaseType<Tset>::type>::value,void>::type >
void addVarCB(C * _this, const std::string &name,
Tget(C::*getter)(void) const, U(C::*setter)(Tset), const std::string &def = "") {
}
int main() {
MyClass c;
addVarCB(&c,std::string("a"),&MyClass::getA,&MyClass::setA,std::string("a"));
//addVarCB(&c,std::string("a"),&MyClass::getS,&MyClass::setA,std::string("a")); // Compiler error
}
这里我们只是简单地推断get和set类型(Tget
和Tset
)。然后,我们剥离这些类型的任何常量或引用,并检查它们是否相同;如果没有,我们会使用enable_if
触发专门化失败。
答案 1 :(得分:1)
只需设置GetType
和SetType
个独立模板参数,让编译器担心它们是否可以转换。
例如。这样:
template< class C, typename T, typename U >
void addVarCB(C * _this, const std::string &name,
T(C::*getter)(void) const, U(C::*setter)(const T&), const std::string &def);
要求setter
的参数是对任何getter
返回的const引用。但是,这个:
template <typename Class, typename GetResult, typename SetArg, typename SetResult>
void addVarCB(Class *instance, std::string const& name,
GetResult (Class::*getter)() const,
SetResult (Class::*setter)(SetArg),
std::string const &def);
允许setter
参数和getter
返回类型不同。现在,假设你想将一个传递给另一个,它只会在它们可以转换时编译(或者你可以使用C ++ 11或Boost.TypeTraits is_convertible
来明确断言)。
...如果不会工作,那么如果您展示addVarCB
内部的内容,或者解释您要实现的目标,可能会有所帮助。