Reputation: 129
I need to write values of different types to a std::wstringstream
. At one time we need to write one ore more values. I have tried to implement it like this:
wstringstream _str;
template<typename ValueType> //(1)
void WriteValue(const ValueType& val)
{
_str << val;
}
template<typename ValueType> //(2)
void WriteValue(const std::vector<ValueType>& vals)
{
for (auto it = vals.begin(); it!= vals.end(); ++it)
{
WriteValue<ValueType>(*it);
_str << L" ";
}
}
template<typename ValueType>
void WriteRecord(const std::wstring& name, const ValueType & val)
{
_str << name;
WriteValue<ValueType>(val);
}
void Foo()
{
int bar = 0;
WriteRecord<int>(L"Lorem", bar); //it's okay
std::vector<int> buz(4, 0);
WriteRecord<int>(L"ipsum", buz); //it's error
}
I got the following error :
"cannot convert argument 2 from 'std::vector< int, std::allocator < int > >'
to 'int &'". As seen compiler tries to pass a vector to (1), not (2).
Why so? Is it possible to make it choose (2) specialized function template?
Upvotes: 1
Views: 58
Reputation: 109089
std::vector<int> buz(4, 0);
WriteRecord<int>(L"ipsum", buz);
// ^^^
You're telling the compiler ValueType
is int
but then you're passing vector<int>
as the argument. The compiler is perfectly capable of deducing template argument types, so stop specifying them everywhere unnecessarily. Your Foo
function should look like this:
void Foo()
{
int bar = 0;
WriteRecord(L"Lorem", bar);
std::vector<int> buz(4, 0);
WriteRecord(L"ipsum", buz);
}
Similarly, remove the explicitly specified template arguments in the calls to WriteValue
in the other functions.
Upvotes: 1
Reputation: 48928
WriteRecord<int>(L"ipsum", buz);
^^^^^
Here you explicitly say that ValueType
should be an int
. So the function signature is:
void WriteRecord(const std::wstring& name, const int& val)
And when you try to pass a std::vector
as second argument, the compiler can't convert the std::vector
to an int
.
For functions, there is rarely a need to explicitly name the type of the template argument, you writing the call like this will work:
WriteRecord(L"ipsum", buz); //Compiler deduces ValueType
If you really need to specify the template argument, use decltype
:
WriteRecord<decltype(buz)>(L"ipsum", buz);
or just write it out (not recommended)
WriteRecord<std::vector<int>>(L"ipsum", buz);
Upvotes: 2