Why are default template arguments only allowed on class templates? Why can't we define a default type in a member function template? For example:
为什么默认模板参数只允许在类模板上使用?为什么我们不能在成员函数模板中定义一个默认类型呢?例如:
struct mycclass {
template<class T=int>
void mymember(T* vec) {
// ...
}
};
Instead, C++ forces that default template arguments are only allowed on a class template.
相反,c++强制默认模板参数只能在类模板上使用。
5 个解决方案
#1
141
It makes sense to give default template arguments. For example you could create a sort function:
给出默认模板参数是有意义的。例如,您可以创建排序函数:
template<typename Iterator,
typename Comp = std::less<
typename std::iterator_traits<Iterator>::value_type> >
void sort(Iterator beg, Iterator end, Comp c = Comp()) {
...
}
C++0x introduces them to C++. See this defect report by Bjarne Stroustrup: Default Template Arguments for Function Templates and what he says
c++ 0x将它们引入到c++中。请参阅Bjarne Stroustrup的缺陷报告:函数模板的默认模板参数以及他所说的内容
The prohibition of default template arguments for function templates is a misbegotten remnant of the time where freestanding functions were treated as second class citizens and required all template arguments to be deduced from the function arguments rather than specified.
函数模板的默认模板参数的禁止是一种错误的残余,在这种情况下,独立函数被视为二等公民,并要求所有模板参数都从函数参数推导出来,而不是指定。
The restriction seriously cramps programming style by unnecessarily making freestanding functions different from member functions, thus making it harder to write STL-style code.
这种限制严重限制了编程风格,因为它不必要地使独立函数与成员函数不同,从而使编写stl样式的代码变得更加困难。
#2
34
To quote C++ Templates: The Complete Guide (page 207):
引用c++模板:完整指南(第207页):
When templates were originally added to the C++ language, explicit function template arguments were not a valid construct. Function template arguments always had to be deducible from the call expression. As a result, there seemed to be no compelling reason to allow default function template arguments because the default would always be overridden by the deduced value.
当模板最初添加到c++语言时,显式函数模板参数不是有效的构造。函数模板参数必须与调用表达式可约。因此,似乎没有令人信服的理由允许默认函数模板参数,因为默认值总是被推断值覆盖。
#3
16
So far, all the proffered examples of default template parameters for function templates can be done with overloads.
到目前为止,函数模板的所有默认模板参数示例都可以通过重载完成。
AraK:
阿拉克:
struct S {
template <class R = int> R get_me_R() { return R(); }
};
could be:
可能是:
struct S {
template <class R> R get_me_R() { return R(); }
int get_me_R() { return int(); }
};
My own:
我自己的:
template <int N = 1> int &increment(int &i) { i += N; return i; }
could be:
可能是:
template <int N> int &increment(int &i) { i += N; return i; }
int &increment(int &i) { return increment<1>(i); }
litb:
litb:
template<typename Iterator, typename Comp = std::less<Iterator> >
void sort(Iterator beg, Iterator end, Comp c = Comp())
could be:
可能是:
template<typename Iterator>
void sort(Iterator beg, Iterator end, std::less<Iterator> c = std::less<Iterator>())
template<typename Iterator, typename Comp >
void sort(Iterator beg, Iterator end, Comp c = Comp())
Stroustrup:
一种:
template <class T, class U = double>
void f(T t = 0, U u = 0);
Could be:
可能是:
template <typename S, typename T> void f(S s = 0, T t = 0);
template <typename S> void f(S s = 0, double t = 0);
Which I proved with the following code:
我用下面的代码证明了这一点:
#include <iostream>
#include <string>
#include <sstream>
#include <ctype.h>
template <typename T> T prettify(T t) { return t; }
std::string prettify(char c) {
std::stringstream ss;
if (isprint((unsigned char)c)) {
ss << "'" << c << "'";
} else {
ss << (int)c;
}
return ss.str();
}
template <typename S, typename T> void g(S s, T t){
std::cout << "f<" << typeid(S).name() << "," << typeid(T).name()
<< ">(" << s << "," << prettify(t) << ")\n";
}
template <typename S, typename T> void f(S s = 0, T t = 0){
g<S,T>(s,t);
}
template <typename S> void f(S s = 0, double t = 0) {
g<S,double>(s, t);
}
int main() {
f(1, 'c'); // f<int,char>(1,'c')
f(1); // f<int,double>(1,0)
// f(); // error: T cannot be deduced
f<int>(); // f<int,double>(0,0)
f<int,char>(); // f<int,char>(0,0)
}
The printed output matches the comments for each call to f, and the commented-out call fails to compile as expected.
打印出来的输出与每次调用f时的注释相匹配,被注释掉的调用未能按预期进行编译。
So I suspect that default template parameters "aren't needed", but probably only in the same sense that default function arguments "aren't needed". As Stroustrup's defect report indicates, the addition of non-deduced parameters was too late for anyone to realise and/or really appreciate that it made defaults useful. So the current situation is in effect based on a version of function templates which was never standard.
因此,我怀疑默认模板参数“不需要”,但可能只是在相同的意义上,默认函数参数“不需要”。正如Stroustrup的缺陷报告所指出的那样,对于任何人来说,添加非推导的参数都太晚了,以至于没有人意识到或者真正理解它使默认值变得有用。因此,当前的情况实际上是基于函数模板的一个版本,而这个版本从来都不是标准的。
#4
4
On Windows, with all versions of Visual Studio you can convert this error (C4519) to a warning or disable it like so:
在Windows上,使用所有版本的Visual Studio,您可以将这个错误(C4519)转换为警告,或者像这样禁用它:
#ifdef _MSC_VER
#pragma warning(1 : 4519) // convert error C4519 to warning
// #pragma warning(disable : 4519) // disable error C4519
#endif
See more details here.
看到更多的细节。
#5
1
What I use is next trick:
我使用的下一个技巧是:
Lets say you want to have function like this:
假设你想要有这样的函数:
template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array)
{
E one(1);
array.add( one );
}
You will not be allowed, but I do next way:
你是不被允许的,但我做下一个:
template <typename T>
struct MyArray_t {
void add(T i)
{
// ...
}
};
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<E, ARR_E>::doStuff()
{
E one(1);
parr_->add( one );
}
So this way you may use it like this:
所以你可以这样使用它:
MyArray_t<int> my_array;
worker<int> w;
w.parr_ = &arr;
w.doStuff();
As we can see no need to explicitly set second parameter. Maybe it will be useful for someone.
我们可以看到,不需要显式地设置第二个参数。也许对某人有用。
#1
141
It makes sense to give default template arguments. For example you could create a sort function:
给出默认模板参数是有意义的。例如,您可以创建排序函数:
template<typename Iterator,
typename Comp = std::less<
typename std::iterator_traits<Iterator>::value_type> >
void sort(Iterator beg, Iterator end, Comp c = Comp()) {
...
}
C++0x introduces them to C++. See this defect report by Bjarne Stroustrup: Default Template Arguments for Function Templates and what he says
c++ 0x将它们引入到c++中。请参阅Bjarne Stroustrup的缺陷报告:函数模板的默认模板参数以及他所说的内容
The prohibition of default template arguments for function templates is a misbegotten remnant of the time where freestanding functions were treated as second class citizens and required all template arguments to be deduced from the function arguments rather than specified.
函数模板的默认模板参数的禁止是一种错误的残余,在这种情况下,独立函数被视为二等公民,并要求所有模板参数都从函数参数推导出来,而不是指定。
The restriction seriously cramps programming style by unnecessarily making freestanding functions different from member functions, thus making it harder to write STL-style code.
这种限制严重限制了编程风格,因为它不必要地使独立函数与成员函数不同,从而使编写stl样式的代码变得更加困难。
#2
34
To quote C++ Templates: The Complete Guide (page 207):
引用c++模板:完整指南(第207页):
When templates were originally added to the C++ language, explicit function template arguments were not a valid construct. Function template arguments always had to be deducible from the call expression. As a result, there seemed to be no compelling reason to allow default function template arguments because the default would always be overridden by the deduced value.
当模板最初添加到c++语言时,显式函数模板参数不是有效的构造。函数模板参数必须与调用表达式可约。因此,似乎没有令人信服的理由允许默认函数模板参数,因为默认值总是被推断值覆盖。
#3
16
So far, all the proffered examples of default template parameters for function templates can be done with overloads.
到目前为止,函数模板的所有默认模板参数示例都可以通过重载完成。
AraK:
阿拉克:
struct S {
template <class R = int> R get_me_R() { return R(); }
};
could be:
可能是:
struct S {
template <class R> R get_me_R() { return R(); }
int get_me_R() { return int(); }
};
My own:
我自己的:
template <int N = 1> int &increment(int &i) { i += N; return i; }
could be:
可能是:
template <int N> int &increment(int &i) { i += N; return i; }
int &increment(int &i) { return increment<1>(i); }
litb:
litb:
template<typename Iterator, typename Comp = std::less<Iterator> >
void sort(Iterator beg, Iterator end, Comp c = Comp())
could be:
可能是:
template<typename Iterator>
void sort(Iterator beg, Iterator end, std::less<Iterator> c = std::less<Iterator>())
template<typename Iterator, typename Comp >
void sort(Iterator beg, Iterator end, Comp c = Comp())
Stroustrup:
一种:
template <class T, class U = double>
void f(T t = 0, U u = 0);
Could be:
可能是:
template <typename S, typename T> void f(S s = 0, T t = 0);
template <typename S> void f(S s = 0, double t = 0);
Which I proved with the following code:
我用下面的代码证明了这一点:
#include <iostream>
#include <string>
#include <sstream>
#include <ctype.h>
template <typename T> T prettify(T t) { return t; }
std::string prettify(char c) {
std::stringstream ss;
if (isprint((unsigned char)c)) {
ss << "'" << c << "'";
} else {
ss << (int)c;
}
return ss.str();
}
template <typename S, typename T> void g(S s, T t){
std::cout << "f<" << typeid(S).name() << "," << typeid(T).name()
<< ">(" << s << "," << prettify(t) << ")\n";
}
template <typename S, typename T> void f(S s = 0, T t = 0){
g<S,T>(s,t);
}
template <typename S> void f(S s = 0, double t = 0) {
g<S,double>(s, t);
}
int main() {
f(1, 'c'); // f<int,char>(1,'c')
f(1); // f<int,double>(1,0)
// f(); // error: T cannot be deduced
f<int>(); // f<int,double>(0,0)
f<int,char>(); // f<int,char>(0,0)
}
The printed output matches the comments for each call to f, and the commented-out call fails to compile as expected.
打印出来的输出与每次调用f时的注释相匹配,被注释掉的调用未能按预期进行编译。
So I suspect that default template parameters "aren't needed", but probably only in the same sense that default function arguments "aren't needed". As Stroustrup's defect report indicates, the addition of non-deduced parameters was too late for anyone to realise and/or really appreciate that it made defaults useful. So the current situation is in effect based on a version of function templates which was never standard.
因此,我怀疑默认模板参数“不需要”,但可能只是在相同的意义上,默认函数参数“不需要”。正如Stroustrup的缺陷报告所指出的那样,对于任何人来说,添加非推导的参数都太晚了,以至于没有人意识到或者真正理解它使默认值变得有用。因此,当前的情况实际上是基于函数模板的一个版本,而这个版本从来都不是标准的。
#4
4
On Windows, with all versions of Visual Studio you can convert this error (C4519) to a warning or disable it like so:
在Windows上,使用所有版本的Visual Studio,您可以将这个错误(C4519)转换为警告,或者像这样禁用它:
#ifdef _MSC_VER
#pragma warning(1 : 4519) // convert error C4519 to warning
// #pragma warning(disable : 4519) // disable error C4519
#endif
See more details here.
看到更多的细节。
#5
1
What I use is next trick:
我使用的下一个技巧是:
Lets say you want to have function like this:
假设你想要有这样的函数:
template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array)
{
E one(1);
array.add( one );
}
You will not be allowed, but I do next way:
你是不被允许的,但我做下一个:
template <typename T>
struct MyArray_t {
void add(T i)
{
// ...
}
};
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<E, ARR_E>::doStuff()
{
E one(1);
parr_->add( one );
}
So this way you may use it like this:
所以你可以这样使用它:
MyArray_t<int> my_array;
worker<int> w;
w.parr_ = &arr;
w.doStuff();
As we can see no need to explicitly set second parameter. Maybe it will be useful for someone.
我们可以看到,不需要显式地设置第二个参数。也许对某人有用。