c++11 - 类的方法(在 shared_ptr 中)可以绑定到特征类中的静态函数吗?
问题描述
从历史上看,我一直使用特征类来保存信息并将其应用到运行相同“算法”的“通用”函数中。仅因特质类而异。例如:https ://onlinegdb.com/ryUo7WRmN
enum selector { SELECTOR1, SELECTOR2, SELECTOR3, };
// declaration
template < selector T> struct example_trait;
template<> struct example_trait<SELECTOR1> {
static constexpr size_t member_var = 3;
static size_t do_something() { return 0; }
};
template<> struct example_trait<SELECTOR2> {
static constexpr size_t member_var = 5;
static size_t do_something() { return 0; }
};
// pretend this is doing something useful but common
template < selector T, typename TT = example_trait<T> >
void function() {
std::cout << TT::member_var << std::endl;
std::cout << TT::do_something() << std::endl;
}
int main()
{
function<SELECTOR1>();
function<SELECTOR2>();
return 0;
}
在处理多态类时,我不确定如何创建“通用”算法。
例如:https ://onlinegdb.com/S1hFLGC7V
下面我创建了一个继承的类层次结构。在此示例中,我有一个基本的包罗万象的示例,它将所有参数默认为某个值(在本例中为 0)。然后每个派生类集都会覆盖特定的方法。
#include <iostream>
#include <memory>
#include <type_traits>
#include <assert.h>
using namespace std;
struct Base {
virtual int get_thing_one() {
return 0;
}
virtual int get_thing_two() {
return 0;
}
virtual int get_thing_three() {
return 0;
}
virtual int get_thing_four() {
return 0;
}
};
struct A : public Base {
virtual int get_thing_one() override {
return 1;
}
virtual int get_thing_three() override {
return 3;
}
};
struct B : public Base {
virtual int get_thing_one() override {
return 2;
}
virtual int get_thing_four() override{
return 4;
}
};
在这里,我创建了一个简单的工厂,不优雅但用于说明目的
// example simple factory
std::shared_ptr<Base> get_class(const int input) {
switch(input)
{
case 0:
return std::shared_ptr<Base>(std::make_shared<A>());
break;
case 1:
return std::shared_ptr<Base>(std::make_shared<B>());
break;
default:
assert(false);
break;
}
}
所以这是感兴趣的类别。它是一个类对来自上述类的数据进行“某事”。下面的方法是一个简单的加法示例,但想象一个更复杂的算法,每种方法都非常相似。
// class that uses the shared_ptr
class setter {
private:
std::shared_ptr<Base> l_ptr;
public:
setter(const std::shared_ptr<Base>& input):l_ptr(input)
{}
int get_thing_a()
{
return l_ptr->get_thing_one() + l_ptr->get_thing_two();
}
int get_thing_b()
{
return l_ptr->get_thing_three() + l_ptr->get_thing_four();
}
};
int main()
{
constexpr int select = 0;
std::shared_ptr<Base> example = get_class(select);
setter l_setter(example);
std::cout << l_setter.get_thing_a() << std::endl;
std::cout << l_setter.get_thing_b() << std::endl;
return 0;
}
如何使 setter 类中的“样板”更通用?我不能像在上面的示例中那样使用特征,因为我不能将静态函数与对象联系起来。那么有没有办法让样板示例更常见?
比如说有一个选择器的某个地方
enum thing_select { THINGA, THINGB, };
template < thing_select T >
struct thing_traits;
template <>
struct thing_traits<THINGA>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_one' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_two' method
}
template <>
struct thing_traits<THINGB>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_three' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_four' method
}
// generic function I'd like to create
template < thing_select T, typename TT = thing_traits<T> >
int perform_action(...)
{
return TT::first_function(..) + TT::second_function(..);
}
理想情况下,我想将上面的类修改为类似于
// Inside setter class further above
int get_thing_a()
{
return perform_action<THINGA>(...);
}
int get_thing_b()
{
return perform_action<THINGB>(...);
}
答案是,也许我不能,我需要将 int shared_ptr 作为参数传递并调用我需要的特定方法,而不是试图将 shared_ptr 方法绑定到静态函数(事后看来,这听起来不像一个好主意......但我想反弹我的想法)
解决方案
进行实际调用的人将需要以一种或另一种方式引用该对象。因此,假设您要perform_action
执行实际调用,则必须传递参数。
现在,如果您真的想在不传递参数的情况下将Base
要调用的函数存储为 in ,则可以利用指向成员函数的指针:static
thing_traits
template <>
struct thing_traits<THINGA>
{
static constexpr int (Base::*first_function)() = &Base::get_thing_one;
...
}
template < thing_select T, typename TT = thing_traits<T>>
int perform_action(Base & b)
{
return (b.*TT::first_function)() + ...;
}
您也可以改为返回一个为您执行调用的函数对象(并且内部函数接受参数)。
这一切都取决于您需要谁来拨打电话,以及您假设您在每个类/模板中都有哪些信息/依赖项。
推荐阅读
- duckdb - CSV 阅读器行为
- python - 使用 python 的随机 Gamma 分布
- java - 模糊匹配Java中的名称列表
- ruby-on-rails - 使用 Ansible 在 Ubuntu 上查找安装 rails 的 gem 路径时出错
- linux - 系统调用仅读/写 1 个字节?
- javascript - try/catch 不执行或捕获错误
- r - R用其他df2的名称替换df1的名称元素
- vue.js - Vuetifty:似乎根本无法更改 Datatables 字体
- asp.net-core - 是否在 .Net 核心端而不是 SQL 端执行 lambda 查询中调用的方法
- sqlite - 无法在 sqlite 中按年月分组,日期为毫秒