With the following code, if I attempt to convert a template array to std::string, instead of the compiler using the expected std::string conversion method, it raises an ambiguity resolution problem (as it attempts to call the array conversion methods):
#include <iostream>
template<typename TemplateItem>
class TestA
{
public:
TemplateItem Array[10];
operator const TemplateItem *() const {return Array;}
operator const std::string() const;
};
template<>
TestA<char>::operator const std::string() const
{
st开发者_StackOverflow中文版d::string Temp("");
return Temp;
}
int main()
{
TestA<char> Test2;
std::string Temp("Empty");
Temp = Test2; //Ambiguity error. std::string or TemplateItem * ?
return 0;
}
What modification do I need to make to the code in order to make it so the code correctly and implicitly resolve to the std::string conversion function? Especially given the const TemplateItem * would be treated as a null-terminated array (which it won't likely be).
First, the reason you have ambiguity: you provide both conversion to char*
and conversion to std::string const
, and std::string
likes them both.
By the way, before getting to your question, the const
in operator std::string const
was once a good idea, advocated by e.g. Scott Meyers, but is nowadays ungood: it prevents efficient moving.
Anyway, re the question, just avoid implicit conversions. Make those conversions explicit. Now I answered that in response to another SO question, and someone (I believe the person was trolling) commented that C++98 doesn't support explicit
type conversion operators. Which was true enough, technically, but pretty stupid as a technical comment. Because you don't need to use the explicit
keyword (supported by C++11), and indeed that's not a good way to make the conversions explicit. Instead just name those conversions: use named member functions, not conversion operators.
#include <iostream>
template<typename TemplateItem>
class TestA
{
public:
TemplateItem Array[10];
TemplateItem const* data() const { return Array; }
std::string str() const;
};
template<>
std::string TestA<char>::str() const
{
return "";
}
int main()
{
TestA<char> test2;
std::string temp( "Empty" );
temp = test2.str(); // OK.
temp = test2.data(); // Also OK.
}
Cheers & hth.
I will add, after thinking about it, here's the reasoning and what should be done:
The operator const TemplateItem *(); Should be deleted.
Why? There never will be an instance where you would want implicit conversion of TestA (or any template class) to a TemplateItem array with an unknown size - because this has absolutely no bounds checking (array could be sizeof 1 or 10 or 1000 or 0) and would likely cause a crash if a calling function or class received the array with no idea what size it is.
If the array is needed, either use the operator[] for direct items, or GetArray (which would signal the user intends to pass an unknown-length array).
Retain operator const std::string. Code will compile. Possible memory issues down the line averted.
(Alf for his efforts has been selected as the 'correct' answer, although this is the more logical option)
精彩评论