c ++函数无法使用模板

时间:2018-05-14 14:28:24

标签: c++ templates inheritance

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

我正在创建一个遗传算法基类,我为其编写了一个针对人口个体的抽象基类。我想要一个通用定义,所以我使用模板来定义fenotype和基因型:

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<>?有人可以帮助我理解编译器如何处理这种继承以及如何解决它?

2 个答案:

答案 0 :(得分:2)

using bitset = boost::dynamic_bitset

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

简而言之:不同(甚至多态相关)类型的向量(和其他容器)不是协变的。就像您无法将std::vector<int>传递给期望std::vector<long>的函数一样,您无法通过期望std::vector<bitstring_individual>的{​​{1}}。

注意:是的,它们是不同的转换,但想法是一样的。

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

如果您希望具体个体没有模板基类提供的其他功能,请执行以下操作:

std::vector<individual<bitset, bitset>>

否则,您的向量无法直接存储个人 - 您必须使用using bitstring_individual = individual<bitset, bitset>; (或std::vector<std::shared_ptr<individual<T, S>>>unique_ptr而不是ref)等所有人口向量

答案 1 :(得分:0)

您的问题实际上涉及C ++中covariance and contravariance个(某些)类型。即使你是'硬编码&#34;您的模板参数,即:

using i_bs_bs = individual<bitset, bitset>;
using std::vector;

class bitstring_individual : public i_bs_bs { ... };

vector<bsi> select_best_half(vector<i_bs_bs> parents, vector<i_bs_bs> children) {
    ...
}

您仍然会在将vector<bitstring_individual>传递给select_best_half()时收到错误消息。为什么?因为,C ++ std::vector<T>中的不是协变类型构造函数

要从链接到维基百科页面中获取示例,假设您的继承类是Animal(基类)和Cat(派生类)。在C ++中,您无法将动画添加到Cats向量中。该向量的所有元素都必须是Cats。同样,正如@ MaxLanghof的回答所解释的那样,您无法将bitstring_individual添加到元素为bitstring_individual基类型的向量中。处理bitstring_individual所需的任何特殊行为都不会适用于vector<i_bs_bs>的元素。