XCODE 4.6 C ++模板函数,函数指针作为模板类中的参数

时间:2013-04-20 21:46:40

标签: c++ xcode templates pointers arguments

我一直在为这个问题苦苦挣扎半天似乎至少XCode 4.6有一个错误,其中模板类的某些声明会违反该语言并允许将const数据从类中传递给带参数的外部函数如果没有const修饰符,则被删除。

以下示例将进行COMPILE,即使是艰难的模板声明 Tcaller :: call()方法指定作为引用传递的const参数 但静态cmp函数提供无用的* const&改性剂。

template< typename T> struct Tcalled
{
    // !!!error - this prototype doesn't protect the data passed to function
    // because it should be declared with const modifiers but it wouldn't compile then.
    // SEE: Below my NOTE for correct function prototype.
        static bool cmp(const Tcalled*& item, const int& key) //<- correct but doesn't work
        static bool cmp(Tcalled* const & item, const int& key) //<- invalid but works!!
        {
            return (item->index = key); /// error - we modify const object here !
        }

    T index;
};

template < typename T> struct Tcaller
{
    Tcaller(){}

    template < typename K, bool (*compare)(const T& item, const K& key) >
    bool call(int k) const { return compare(data, k); }

    T       data;

};


int main(int argc, char *argv[])
{
    const Tcaller<Tcalled<int>* > tmp;  // <- const data
    int k = 1;

    tmp.call<int,Tcalled<int>::cmp>(k);  //call here WILL modify const data !!

}

问题是:我如何强制XCode遵守规则并允许我进行原型设计 我为模板参数声明的静态函数?至于现在这些是我在正确声明静态方法时得到的XCode错误:

没有匹配的成员函数来调用'call' 忽略候选模板:模板参数'compare'

的显式指定参数无效

谢谢!

1 个答案:

答案 0 :(得分:2)

大概你的意思是当参数被声明为Tcalled<T>* const & item并且cmp的正文应该使用==而不是=时它会起作用。

您对模板参数的实例化方式存在误解。它不仅仅是模板参数的复制粘贴替换。您希望const T&T实例化为Tcalled<int>*时等同于const Tcalled<int>*&;也就是说,“指向const Tcalled<int>的指针。

但是,这是错误的,const适用于整个T类型。实际上,在实例化之后,const T&相当于Tcalled<int>* const&。这就是将声明为Tcalled* const & item的参数正常工作的原因。

要将此声明用作const Tcalled<T>*& item声明,必须更改许多内容:

  1. call函数模板参数的定义如下:

    template < int (*compare)(T& item) >
    

    也就是说,函数指针类型需要T&,而不是const T&。这是有道理的,因为cmp函数根本没有引用const对象(它引用非const指针)。

  2. call函数不应为const

    int call() { return compare(data); }
    

    这是因为它将其成员T传递给compare,这是对非const对象的引用(指针本身不是const)。如果它是const函数,则无法执行此操作,因为它无法保证compare不会修改对象。

  3. Tcaller必须使用T const Tcalled<int>*进行实例化:

    Tcaller<const Tcalled<int>* > tmp;