1

我写了以下函数:

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 = "");

现在我意识到,如果吸气剂返回,即使这样也会失败

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。

4

2 回答 2

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 类型(TgetTset分别)独立推导。然后我们去除这些类型的任何常量或引用并检查它们是否相同;如果没有,我们会使用enable_if.

于 2012-10-02T18:41:36.483 回答
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);

要求 that的参数是对任何返回setter值的 const 引用。getter然而,这:

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.TypeTraitsis_convertible来明确断言)。


...如果这不起作用addVarCB,如果你展示里面的内容,或者解释你想要实现的目标,它可能会有所帮助。

于 2012-10-02T18:22:02.130 回答