gpt4 book ai didi

c++ - 完全专用类作为模板函数参数

转载 作者:太空狗 更新时间:2023-10-29 23:04:04 26 4
gpt4 key购买 nike

我编写了两个不同的容器类,它们具有相同的接口(interface),但使用不同的成员数据和算法来操作它们的成员。我还有一个模板函数,它接受一个容器并进行一些有用的计算:

class Container1
{
// implementation here
};

class Container2
{
// implementation here
};

template<typename ContainerType>
void my_function(ContainerType const& container, /* other parameters */)
{
// ...
}

令我困扰的是 'my_function' 应该只接受 Container1Container2 , 但这不是由代码表示的,因为 ContainerType可以是任何类型。该函数由容器类型模板化,因为无论容器的内部实现是什么,它都做同样的事情。我正在考虑 Container1 的变体和 Container2将是模板类的完全特化。然后我可以更具体地说明 my_function 的论点:

template<typename T>
class Container;

// Tags to mark different container types
struct ContainerType1 { };
struct ContainerType2 { };

template<>
class Container<ContainerType1>
{
// implementation
};

template<>
class Container<ContainerType2>
{
// implementation
};

template<typename T>
void my_function(Container<T> const& container, /* other parameters */)
{
}

在第一种情况下,如果'ContainerType' 没有my_function 要求的接口(interface),使用错误的模板参数编译将失败。 ,这不是很有用。在第二种情况下,如果我提供 Container<ContainerType1> 以外的任何其他内容,我也会收到编译器错误(模板参数推导失败)。或 Container<ContainerType2> , 但我更喜欢它,因为它提供了有关预期模板参数类型的提示。

您对此有何看法?这是一个好的设计理念吗?您认为值得更改代码吗?还有许多其他功能,例如 my_function在代码中,有时他们期望什么样的模板参数并不明显。我还有哪些其他选择 my_function更具体?我知道 Boost Concept Check Library 的存在。为了争论,假设我不想使用继承和虚函数来解决问题。如果与讨论相关,Container1的公共(public)接口(interface)和 Container2是通过使用 CRTP 强加的。将来可能会有更多的容器类。

最佳答案

这类问题有几种解决方案。

您的解决方案(将您的类型实现为 template 特化)是一个,但我不是特别喜欢。

另一个是CRTP:

template<typename T>
struct Container {
// optional, but I find it helpeful
T* self() { return static_cast<T*>(this); }
T const* self() const { return static_cast<T const*>(this); }

// common code between every implementation goes here. It accesses itself through self(), never this
};

class ContainerType1: public Container<ContainerType1> {
// more details
};
class ContainerType2: public Container<ContainerType2> {
// more details
};

这是 CRTP 的核心。

然后:

template<typename T>
void my_function(Container<T> const& container_, /* other parameters */)
{
T const& container = *(container.self());
}

鲍勃是你的叔叔。作为奖励,这提供了放置通用代码的位置。

另一个选项是标记特征类,它标记了你想要支持的类型,比如 iterator_traits .

template<typename T>
struct is_container : std::false_type {};
template<>
struct is_container<ContainerType1> : std::true_type {};
template<>
struct is_container<ContainerType2> : std::true_type {};

您甚至可以执行 SFINAE 样式模式匹配来检测基本类型(例如迭代器的工作方式)。

现在您的方法可以在 is_container<T>::value 上进行测试,或在 is_container<T>{} 上进行标签调度.

关于c++ - 完全专用类作为模板函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23802903/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com