【问题标题】:Yet another virtual template workaround另一个虚拟模板解决方法
【发布时间】:2014-08-04 13:58:37
【问题描述】:

抱歉,这是一个热门主题(例如here),但我找不到合适的解决方案来解决我的问题。显示代码会太长且令人困惑,所以我只显示伪代码;这是一个关于设计的问题,我在这里寻找适用于 C++(11) 的模式。

目标:我正在处理多维数组(例如,包含向量场的 4D 数组),并且我想访问具有 nD 坐标和动态边界条件的数组元素。

对象:

  • 数组:将数据作为一维数组包含在内存中并重载下标 (value_type operator[] (unsigned));
  • 索引器:存储 n 维数组的维度,并将 n 维坐标转换为 1 维索引 (unsigned operator() (Coordinates));
  • 边界:要么转换 n 维坐标(如周期性边界),要么返回默认值(例如,容器外的空值)。

要求

  • 坐标类型应模板化(应接受任何数字类型);
  • 边界条件可以动态修改。

问题:

给定一个具有边界条件的 n-D 容器,我希望给定坐标处的值请求如下所示:

value_type operator() ( Coordinates )
{

    if ( Boundary.transforms_coordinates )
    {
        /**
         * 1) Ensure the coordinates are inbound by applying boundary conditions; 
         * 2) Use the Indexer to find the corresponding 1D index.
         */
        return Array[ Indexer(
            Boundary.transform( Coordinates )
        ) ];
    }
    else
    {
        if ( Indexer.coordinates_are_inbound( Coordinates ) )
            return Array[ Indexer(Coordinates) ];
        else
            return Boundary.outbound_value;
    }

}

我不能解决的问题是:如果边界是动态设置的,它的类型不能是模板值,所以需要一个指向边界接口的指针。但是,该接口无法定义虚拟模板方法transform 来接受不同类型的坐标(更不用说纯虚拟坐标了)。

我猜这里存在一个基本的设计缺陷,如果您能告诉我在哪里,最好是如何纠正它,我将不胜感激。也很抱歉问题的长度;这可以通过我不知道的设计(原型)模式来解决。

【问题讨论】:

  • "坐标类型应该是模板化的(应该接受任何数字类型);" - 为什么? int64 和 double 怎么会不够?你需要加倍吗?
  • 所以我想我可以系统地将浮点值转换为 double 和整数值转换为 int64 你是对的,但它并没有从技术上解决可以接受不同坐标容器的事实(指针+大小,或固定大小的数组,或向量等)。将容器约束到特定对象也可以,但这缺乏灵活性并增加了代码的复杂性。
  • 这是一个可以接受的解决方案;我可以创建 IntegerCoordinates 和 DoubleCoordinates 对象,并从这些对象中的各种容器实现适配器。
  • @sh3lijohn 如果这些是您的 3 个容器,请写 array_view<T> 可以免费查看其中任何一个。并将坐标标量类型限制在合理的范围内(intsize_t
  • @Yakk 非常感谢,我认为您的 cmets 表明我需要进一步改进我所说的“坐标”,这可能就是我最初被卡住的原因。 :)

标签: c++ arrays templates


【解决方案1】:

我要感谢 @Yakk 的出色建议,但我想我将使用数组容器的隐式扩展来访问边界值。

这是因为当我想要访问可能受边界条件影响的值时,我不需要完整的容器接口,而只是一种访问方法;我应该知道程序中何时需要边界条件,何时不需要。这是一个伪代码:

struct BoundedContainerAccessor
{
    Array *data;
    Indexer *indexer;

    void accept( Array& a, Indexer& i )
    {
        data = &a;
        indexer = &i;
    }

    template <class T>
    value_type operator() ( T coordinates )
    {
        if (indexer->coordinates_are_inbound( coordinates ))
        {
            return data->[indexer->( coordinates )];
        }
        else
        {
            // Implementation-specific, either:
            // return a value, throw an error, or transform coordinates
        }
    }
};

【讨论】:

    猜你喜欢
    • 2011-02-25
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2016-09-28
    • 2011-12-19
    相关资源
    最近更新 更多