25.2.5.1 Default Function Template Arguments
Naturally, default template arguments can also be useful for function templates. For example:
template
Targ et to(Source arg) // convert Source to Target
{
stringstream interpreter;
Targ et result;
if (!(interpreter << arg) // write arg into stream
|| !(interpreter >> result) // read result from stream
|| !(interpreter >> std::ws).eof()) // stuff left in stream?
throw runtime_error{"to<>() failed"};
return result;
}
A function template argument needs to be explicitly mentioned only if it cannot be deduced or if
there is no default, so we can write:
auto x1 = to<string,double>(1.2); // very explicit (and verbose)
auto x2 = to
auto x3 = to<>(1.2); // Target is defaulted to string; Source is deduced to double
auto x4 = to(1.2); // the <> is redundant
If all function template arguments are defaulted, the <> can be left out (exactly as in function tem-
plate specializations; §25.3.4.1).
This implementation of to() is a bit heavyweight for combinations of simple types, such as
to
to
among scalar numeric types, I tend to prefer narrow_cast<>() (§11.5).
感觉挺牛的,记录一下。
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;
template<typename Target=string, typename Source=string>
Target to(Source arg) {
stringstream interpreter;
Target result;
if (!(interpreter << arg)
|| !(interpreter >> result)
// || !(interpreter >> ws).eof()
)
throw runtime_error{"to<>() failed"};
return result;
}
int main() {
cout << to<int>("7") << endl;
}
原文见 The C++ Programming Language 4th Edition 第 730 页