C++函数无法使用模板为基类的子类派生模板

标签 c++ templates inheritance

我对模板有点陌生,当我以设置模板的方式从基类继承时,我不明白编译器如何派生子类的模板。

我正在创建一个遗传算法基类,我已经为群体中的个体编写了一个抽象基类。我想要一个通用的定义,所以我使用模板来定义表型和基因型:

template<typename T, typename S>
class individual {
    public:
        individual(S& fenotyp, T& genotyp) :
            fenotype(fenotyp), genotype(genotyp) {}
        ...
        S fenotype;

        T genotype;
        ...
};

当个体是位串时,我有以下子类:

class bitstring_individual : public individual<boost::dynamic_bitset<>,
    boost::dynamic_bitset<>> {
    public:
        using individual::individual;
        ...
};

现在我不再需要使用模板括号了。再往下看,我有一个给出人口 std::vector<individual<T,S>> 的函数。 ,返回适应度最高的一半。这适用于任何类型的个人,因此我们可以保持定义的通用性:

template<typename T, typename S>
std::vector<individual<T,S>> select_best_half(std::vector<individual<T,S>> parents,
        std::vector<individual<T,S>> children) {
            ...
        }

但是,如果我调用这个函数,我会得到 error: no matching function for call to select_best_half(...)编译器说 template argument deduction/substitution failed:mismatched types ‘individual<T, S>’ and ‘bitstring_individual' .

bitstring_individual 的定义中我们看到:

bitstring_individual : individual<boost::dynamic_bitset<>,boost::dynamic_bitset<>>

那么为什么编译器不理解模板应该是 boost::dynamic_bitset<> ?有人可以帮助我了解编译器如何处理这种继承以及如何修复它吗?

最佳答案

(using bitset = boost::dynamic_bitset)

您的bitstring_individualindividual<bitset, bitset>相同,并且编译器理所当然地不会识别它们。是的,一个继承了另一个,但这并不使它们在任何地方都可以互换 - 特别是当用作模板参数时。

简而言之:不同(甚至多态相关)类型的 vector (和其他容器)不是协变的。就像你无法通过 std::vector<int>到一个期望 std::vector<long> 的函数你不能通过 std::vector<bitstring_individual>其中 std::vector<individual<bitset, bitset>>预计。

注意:是的,它们是不同的转换,但思想是相同的。

想象一下sizeof(individual<bitset, bitset>) = 32bitstring_individual添加一些成员,以便 sizeof(bitstring_individual) = 48 。如果编译器推导出T = S = bitset ,那么它会生成一个包含 std::vector<individual<bitset, bitset>> 的方法签名,因此是一个元素大小为 32 的 vector 。但是当您尝试调用它时,您传递的是一个元素大小为 48 的 vector 。这些 vector 不是协变的,这必然会导致问题。

如果您希望具体个体除了模板化基类提供的功能之外没有其他功能,只需执行以下操作:

using bitstring_individual = individual<bitset, bitset>;

否则,您的 vector 无法直接存储个体 - 您必须使用类似 std::vector<std::shared_ptr<individual<T, S>>> 的内容(或者 unique_ptrref 而不是 shared_ptr )对于所有群体 vector 。

关于C++函数无法使用模板为基类的子类派生模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50332802/

相关文章:

c++ - 优化循环并避免模板特化中的代码重复

c++ - 模板中的二叉树

python - 访问 python 父类(super class)属性时遇到问题

java - 子类中的空方法有解决办法吗?

Java泛型问题

c++ - C++ 中精确到毫秒的基准测试?

c++ - DirectX 9 中的简单剪辑

c++ - 具有完整类型信息的循环依赖

c++ - 即使返回 true,CTRL+TAB 快捷方式的 Qt eventFilter 也会被进一步处理

c# - 找到最好的区间匹配结果