如果使用 CRTP,如何在存在的情况下调用派生函数,否则使用默认值?
How to call function in derived if exists else use a default if using CRTP?
我有一个用于某些结构的辅助库 class,它使用 CRTP 来帮助我获取有关它们的一些信息:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
};
我已经在我的代码库的各种库中定义了使用它的结构,我希望有一种方法来记录它们。我的第一个想法是这样的:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
virtual void print(std::ostream& out) const { out << "(" << sizeof(T) << ")"; }
};
但后来我意识到,由于几个原因,这是行不通的 - 其中之一是添加虚拟实际上改变了 POD 数据之外的大小。
有没有办法在没有 virtual 关键字的情况下让我有一个使用上述实现的默认 toStr 方法,除非特定的派生 class T 有一个实现,在这种情况下它会遵从那个实现?
我认为执行此类操作的最直接方法是分派到派生 class 可以根据需要隐藏的不同非虚拟函数。例如:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
void print(std::ostream &out) const {
// Cast to derived, call do_print. This will be derived's do_print
// if it exists and MyHelper's otherwise.
static_cast<T const*>(this)->do_print(out);
}
void do_print(std::ostream& out) const {
out << "(" << sizeof(T) << ")";
}
};
struct A : MyHelper<A> {
// no do_print, so MyHelper<A>'s will be used
int x;
};
struct B : MyHelper<B> {
// B's do_print is found and used in MyHelper<B>::print
void do_print(std::ostream &out) const {
out << "Hello!\n";
}
};
template<typename T>
void foo(MyHelper<T> const &r) {
r.print(std::cout);
}
int main() {
A a;
B b;
foo(a);
foo(b);
}
输出:
(4)Hello!
您也可以使用 SFINAE 构建一些不需要第二个成员函数的东西,但我怀疑增加的复杂性是否值得。
我有一个用于某些结构的辅助库 class,它使用 CRTP 来帮助我获取有关它们的一些信息:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
};
我已经在我的代码库的各种库中定义了使用它的结构,我希望有一种方法来记录它们。我的第一个想法是这样的:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
virtual void print(std::ostream& out) const { out << "(" << sizeof(T) << ")"; }
};
但后来我意识到,由于几个原因,这是行不通的 - 其中之一是添加虚拟实际上改变了 POD 数据之外的大小。
有没有办法在没有 virtual 关键字的情况下让我有一个使用上述实现的默认 toStr 方法,除非特定的派生 class T 有一个实现,在这种情况下它会遵从那个实现?
我认为执行此类操作的最直接方法是分派到派生 class 可以根据需要隐藏的不同非虚拟函数。例如:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
void print(std::ostream &out) const {
// Cast to derived, call do_print. This will be derived's do_print
// if it exists and MyHelper's otherwise.
static_cast<T const*>(this)->do_print(out);
}
void do_print(std::ostream& out) const {
out << "(" << sizeof(T) << ")";
}
};
struct A : MyHelper<A> {
// no do_print, so MyHelper<A>'s will be used
int x;
};
struct B : MyHelper<B> {
// B's do_print is found and used in MyHelper<B>::print
void do_print(std::ostream &out) const {
out << "Hello!\n";
}
};
template<typename T>
void foo(MyHelper<T> const &r) {
r.print(std::cout);
}
int main() {
A a;
B b;
foo(a);
foo(b);
}
输出:
(4)Hello!
您也可以使用 SFINAE 构建一些不需要第二个成员函数的东西,但我怀疑增加的复杂性是否值得。