如何将派生 class 的 std::list 而不是父 class 的 std::list 传递给函数?
How to pass std::list of derived class instead of a std::list of parent class to a function?
为什么第二次调用 print_all
函数会导致 静态语义错误?
#include <list>
using std::list;
class foo {
// ...
};
class bar : public foo {
// ...
};
static void print_all(list<foo*>& L) {
// ...
}
list<foo*> LF;
list<bar*> LB;
// ...
print_all(LF); // works fine
print_all(LB); // static semantic error
std::list
是一个模板 class,这意味着,需要用一个类型实例化,以获得所需模板 class 的完整 class 定义。当 std::list
被 foo
和 bar
实例化时,我们得到完全不同的类型。这意味着 bar
是 foo
(由于继承),但 std::list<foo*>
与 std::list<bar*>
是不同的类型。因此,根据给定的定义,print_all(std::list<foo*> &L)
只能采用指向 foo
的 指针列表。
问题的最简单解决方案是templated function。使 print_all
函数模板化,它也可以接受其他类型(即 std::list<foo*>
、std::list<bar*>
等...)。
template<typename Type> // --> template parameter
void print_all(std::list<Type*> const& L) // --> function parameter
// ^^^^^^ --------> use `const-ref` as the list is
// not being modified inside the function
{
// print the list
}
但是,它现在也将接受其他类型,例如 std::list<int*>
、std::list<float*>
等(所有其他可能的类型)。这可能不是您想要的行为。还有我们所谓的"Substitution Failure Is Not An Error" (SFINAE) technique, by which one can restrict the instantiation of the templated print_all
function, if and only if, the template Type
std::is_base_of
foo
class。像
#include <type_traits> // std::enable_if, std::is_base_of
template<typename T>
auto print_all(std::list<T*> const& L)-> std::enable_if_t<std::is_base_of_v<foo, T>> // in C++14
// or
// auto print_all(std::list<T*> const& L)-> typename std::enable_if<std::is_base_of<foo, T>::value>::type // in C++11
{
// print the list
}
为什么第二次调用 print_all
函数会导致 静态语义错误?
#include <list>
using std::list;
class foo {
// ...
};
class bar : public foo {
// ...
};
static void print_all(list<foo*>& L) {
// ...
}
list<foo*> LF;
list<bar*> LB;
// ...
print_all(LF); // works fine
print_all(LB); // static semantic error
std::list
是一个模板 class,这意味着,需要用一个类型实例化,以获得所需模板 class 的完整 class 定义。当 std::list
被 foo
和 bar
实例化时,我们得到完全不同的类型。这意味着 bar
是 foo
(由于继承),但 std::list<foo*>
与 std::list<bar*>
是不同的类型。因此,根据给定的定义,print_all(std::list<foo*> &L)
只能采用指向 foo
的 指针列表。
问题的最简单解决方案是templated function。使 print_all
函数模板化,它也可以接受其他类型(即 std::list<foo*>
、std::list<bar*>
等...)。
template<typename Type> // --> template parameter
void print_all(std::list<Type*> const& L) // --> function parameter
// ^^^^^^ --------> use `const-ref` as the list is
// not being modified inside the function
{
// print the list
}
但是,它现在也将接受其他类型,例如 std::list<int*>
、std::list<float*>
等(所有其他可能的类型)。这可能不是您想要的行为。还有我们所谓的"Substitution Failure Is Not An Error" (SFINAE) technique, by which one can restrict the instantiation of the templated print_all
function, if and only if, the template Type
std::is_base_of
foo
class。像
#include <type_traits> // std::enable_if, std::is_base_of
template<typename T>
auto print_all(std::list<T*> const& L)-> std::enable_if_t<std::is_base_of_v<foo, T>> // in C++14
// or
// auto print_all(std::list<T*> const& L)-> typename std::enable_if<std::is_base_of<foo, T>::value>::type // in C++11
{
// print the list
}