开发者

C++ template class and return type as a constraint

开发者 https://www.devze.com 2023-04-11 18:59 出处:网络
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 h

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号