作为对象成员或模板参数的不同行为

时间:2012-11-21 14:56:31

标签: c++ templates

我试图为成员函数指针创建一个模板助手,主要的想法是能够做到这样的事情:

template <typename T, typename R> struct TStruct
{
    typedef T value_type;
    typedef R return_type;

    R Function(T &);
};

struct Struct
{
    int Function(const int &);
};

typedef TStruct<const int &, int> A;

FunctionPointer<A, A::return_type, A::value_type>::pointer p = &A::Function;
typedef FunctionPointer<Struct, int, const int &>::pointer FPointer;

在做这件事的时候,我意识到在没有助手的情况下声明指针的时间更短(这不是现在的问题;)但它让我感到一种我不理解的错误。让我们知道我们有两个版本的帮手:

template <typename Type, typename Return, typename Parameter> struct Good
{
    typedef Return (Type::*pointer)(Parameter);
};

template <typename Type, typename Return, typename Parameter, Return (Type::*Pointer)(Parameter)> struct Bad
{
    typedef Parameter pointer;
};

Good将成员函数类型的指针定义到结构体中,Bad将其定义为模板参数,然后typedef将其定义到结构体中。 / p>

使用Good结构我的测试程序编译:

int main(int argc, char **argv)
{
    // No compilation errors
    Good<A, A::return_type, A::value_type>::pointer GoodTStructPtr = &A::Function;
    Good<Struct, int, const int &>::pointer GoodStructPtr = &Struct::Function;

    return 0;
}

但是如果使用Bad结构,则会出现编译错误:

int main(int argc, char **argv)
{
    // invalid initialization of reference of type ‘const int&’
    // from expression of type ‘int (TStruct<const int&, int>::*)(const int&)’
    Bad<A, A::return_type, A::value_type, &A::Function>::pointer BadTStructPtr = &A::Function;

    // invalid initialization of reference of type ‘const int&’
    // from expression of type ‘int (Struct::*)(const int&)’
    Bad<Struct, int, const int &, &Struct::Function>::pointer BadStructPtr = &Struct::Function;

    return 0;
}

AFAIK,Good::pointerBad::pointer都属于Return (Type::*)(Parameter)类型,因此他们必须能够指向&A::FunctionStruct::Function,但我是显然错了,但我不知道为什么。 似乎当类型被声明为模板化对象主体并且声明为模板参数时,会有不同的行为。

所以问题是:为什么不将Bad::pointer作为指向&A::Function&Struct::Function 的函数指针?

1 个答案:

答案 0 :(得分:2)

你的意思是?

template <typename Type, 
          typename Return, 
          typename Parameter, 
          Return (Type::*Pointer)(Parameter)> struct Bad
{
    typedef Pointer pointer;
    //      ^^^^^^^ (not Parameter)
};