【问题标题】:default template arguments in c++C++ 中的默认模板参数
【发布时间】:2010-02-24 18:19:38
【问题描述】:

假设我有一个函数模板 StrCompare

template<typename T=NonCaseSenCompare>//NonCaseSenCompare is a user defined class look at the detailed code below.
int StrCompare(char* str1, char* str2)
{
...
}

现在在主函数中我写了一行

char* str1="Zia";
char* str2="zia";
int result=StrCompare(str1,str2);

它应该可以工作,因为我们提供了一个默认模板参数,但它没有
编译器给出以下错误
调用 `StrCompare(char*&, char*&)' 没有匹配的函数 现在详细代码由

给出
#include<iostream.h>
class CaseSenCompare
{
public: 
static int isEqual(char x, char y)
{
return x==y;
}
};
class NonCaseSenCompare
{
public:
static int isEqual(char x,char y)
{
char char1=toupper(x);
char char2=toupper(y);
return char1==char2;
}
};
template<typename T=NonCaseSenCompare>
int StrCompare(char* str1, char* str2)
{
for(int i=0;i < strlen(str1)&& strlen(str2);i++)
{
if(!T::isEqual(str1[i],str2[i]))
return str1[i]-str2[i];
}
return strlen(str1)-strlen(str2);
}

main()
{
char* ptr1="Zia ur Rahman";
char* ptr2="zia ur Rahman";
int result=StrCompare(ptr1,ptr2);//compiler gives error on this line
cout<<result<<endl;
system("pause");
}

如果我写

int result=StrCompare<>(ptr1,ptr2);

编译器给出同样的错误信息。

【问题讨论】:

  • 我认为我们永远不会摆脱“亲爱的干草!” :D

标签: c++ templates c++03


【解决方案1】:

正如gfAndreyT 已经写的那样,函数模板不能有默认模板参数。但是,如果您将比较器转换为函数对象,您仍然可以使用默认函数参数:

template<typename Comp>
int StrCompare(char* str1, char* str2, Comp = NonCaseSenCompare())
{
  ...
}

您现在可以像这样拨打StrCompare()

StrCompare("abc","aBc",CaseSenCompare());

或者像这样:

StrCompare("abc","aBc"); // uses NonCaseSenCompare

比较器必须如下所示:

struct CaseSenCompare {
  bool operator()(char x, char y) const {return x==y;}
};

相应地调整StrCompare()

【讨论】:

  • 是的,我知道我们不能在函数模板的情况下提供默认模板参数。谢谢
【解决方案2】:

§14.1/9

默认模板参数不应 在函数模板中指定 声明或函数模板 定义,也不在 的模板参数列表 类成员的定义 模板。

一个简单的解决方法是将它移到一个类中:

template<typename T=NonCaseSenCompare>
struct StrCompare {
    static int compare(char* str1, char* str2) { /* ... */ }
};

【讨论】:

  • 这么想,但不确定。
  • 然后我们在哪里指定默认模板参数
【解决方案3】:

首先,函数模板不支持默认模板参数,只有类模板支持。

其次,即使所有 class 模板参数都有默认参数,您仍然必须指定一个空的 &lt;&gt; 来引用该类模板。

【讨论】:

  • 是不是说函数模板不能给默认模板参数,类成员函数只能给默认模板参数?
  • 我明白了,是的,你是对的,在函数模板的情况下,我们不能提供默认模板参数
【解决方案4】:

我用的是下一个技巧;

假设你想拥有这样的功能

template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array)
{
    E one(1);
    array.add( one );
}

你不会被允许,但我会这样做:

template <typename E, typename ARR_E = MyArray_t<E> >
class worker {
public:
    /*static - as you wish */ ARR_E* parr_;
    void doStuff(); /* do not make this one static also, MSVC complains */
};

template <typename E, typename ARR_E>
void worker::doStuff<E, ARR_E>::getChunks()
{
    E one(1);
    parr_->add( one );
}

这样你就可以这样使用它了。

MyArray_t my_array;
worker<int> w;
w.parr_ = &arr;
w.doStuff();

我们可以看到不需要显式设置第二个参数。 也许它会对某人有用。

【讨论】:

  • 在发布多个问题的复制和粘贴样板/逐字答案时要小心,这些往往会被社区标记为“垃圾邮件”。
猜你喜欢
  • 2015-05-09
  • 2012-03-26
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 2011-08-27
  • 1970-01-01
  • 2011-07-15
  • 2015-08-15
相关资源
最近更新 更多