2013-04-20 86 views
0

我一直在为这个问题奋斗了大约半天,至少XCode 4.6有一个bug模板类的某些声明会违反语言并允许将类内的常量数据传递给外部函数,其参数delcared as const修饰符。XCODE 4.6使用函数指针作为模板类中的参数的C++模板函数

下面的例子将编译, Tcaller ::()方法调用的甚至强硬模板声明规定作为参考 但静态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的错误,我是说我正确宣告我的静态方法:

呼叫到“呼叫” 候选模板不匹配的成员函数忽略:模板参数“比较”

无效显式指定的参数

谢谢!

+0

'常量Tcalled *'是指针为const Tcalled,'Tcalled * const'是常量指针Tcalled。他们是不同的东西 – yngccc 2013-04-20 22:04:08

回答

2

大概你的意思是说,它的工作原理是当参数声明为Tcalled<T>* const & itemcmp的主体应该使用==而不是=

您对模板参数实例化的方式存在误解。这不仅仅是模板参数的复制粘贴替换。你预计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函数模板argume NTS应定义像这样:

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

    即,函数指针类型需要T&,而不是一个const T&。这是有意义的,因为cmp函数根本不参考const对象(它引用非const指针)。

  2. call功能不应const

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

    这是因为它通过其构件T比较,这是一个参考到非const对象(指针本身不是const)。它不能这样做,如果它是const函数,因为它不能保证compare不会修改该对象。

  3. Tcaller必须T作为const Tcalled<int>*被实例:

    Tcaller<const Tcalled<int>* > tmp; 
    
+0

感谢您花时间回答。我想到了这一点,但仍然如此,编译器允许实际修改const对象 - 请参阅上面我更新的代码。我不应该依赖编译器的消息或警告吗? Plus - 仍然是一个有效的问题 - 如何在外部静态函数中使用正确的方法来保存'constness'? – seeoneself 2013-04-20 22:02:05

+0

@seeoneself看到我的编辑修复。 – 2013-04-20 22:04:59

+0

我很害怕这个解决方案是诚实的!我最初做了,但是这迫使我在模板中只有const数据 - 因为这只是一个虚拟的例子,它可能看起来像一个很好的解决方案,但在实际的代码中,我会坚持const数据类型作为模板参数,这是不可接受的这是非const数据的容器类.. confused:S – seeoneself 2013-04-20 22:10:12