C++ template class and return type as a constraint
Sorry for this foolish question, but I'm quite new to C++.
I have a base class called AlertInfoBase
in my project. It has some dozens of subclasses. Now I want to have a class template, which will have a method filter()
. This method will always return a reference to AlertInfoBase
. Here's the code:
template <class T>
class AlertInfoFilter
{
public:
AlertInfoFilter() { }
AlertInfoBase & filter(T & alertInfo)
{
return alertInfo;
}
};
As you can see, the method filter just returns the passed parameter. My goal is to create alter开发者_JAVA技巧nate implementations of filter()
using template specialization, but this is not my problem/question right now.
The strange thing I'm facing is that, when I pass an instance of a class to filter()
, which is subclassed from AlertInfoBase
, everything works as expected. It returns same reference, but when I pass an instance of a class which doesn't implement AlertInfoBase
, the project doesn't compile. Actually this is the kind of behavior I want to have, but some clarification why is this happening would be nice. Is the compiler smart enough to guess that I fill the method with incorrect parameter due to return type?
Thanks
P.S. I'm using MinGW compiler.
You can think of templates as a code generation mechanism. A particular instantiation of a template is identical in most ways to manually written code that just substituted the template argument where appropriate. In your example, if you instantiated AlertInfoFilter
with a std::string
(as an example of a class that does not inherit from AlertInfoBase), then the following code would be generated (approximately):
class AlertInfoFilter_string
{
public:
AlertInfoFilter_string() { }
AlertInfoBase & filter(std::string & alertInfo)
{
return alertInfo;
}
};
Clearly, this should not compile.
Yes, the compiler is exactly smart enough to know that. It's using the implicit conversion from child to base class when T descends from AlertInfoBase
and isn't able to convert your T
to the return type in other cases.
It would also work with a class that implemented operator AlertInfoBase&
in an unrelated class but that would just add confusion so I don't suggest it.
filter
takes a T
as input and converts it to an AlertInfoBase
. If T
is now a type that is not a sub-class of AlertInfoBase
, and does not offer a conversion, then the program cannot be compiled.
Actually, the compiler does something ver close to taking the code, substituting T for the actual argument and compiling the template. This happens once for every different T you use in your program.
When you pass eg. an int
, you get:
class AlertInfoFilter
{
public:
AlertInfoFilter() { }
AlertInfoBase & filter(int & alertInfo)
{
return alertInfo;
}
};
which obviously doesn't compile.
精彩评论