我一直在为这个问题苦苦挣扎半天似乎至少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'
的显式指定参数无效谢谢!
答案 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
声明,必须更改许多内容:
call
函数模板参数的定义如下:
template < int (*compare)(T& item) >
也就是说,函数指针类型需要T&
,而不是const T&
。这是有道理的,因为cmp
函数根本没有引用const
对象(它引用非const
指针)。
call
函数不应为const
:
int call() { return compare(data); }
这是因为它将其成员T
传递给compare,这是对非const
对象的引用(指针本身不是const
)。如果它是const
函数,则无法执行此操作,因为它无法保证compare
不会修改对象。
Tcaller
必须使用T
const Tcalled<int>*
进行实例化:
Tcaller<const Tcalled<int>* > tmp;