模板 class 作为参数模板:MSVC 错误 - 错误 C2977:模板参数过多 (C++98)

Template class as parameter template: MSVC error - error C2977: too many template arguments(C++98)

我需要在 MSVC(C++98) 中构建我的代码。我用模板 class 参数声明了一个模板 class。结果我在 MSVC 编译期间遇到错误: 错误 C2977:'Set':模板参数过多

Gcc 可以很好地构建此代码。

你可以自己试试: https://godbolt.org/z/YJXLX7

给你这个代码:

#include <iostream>
#include <vector>

class Iterator
{
public:
    virtual int size() = 0;
};

template <template<typename> class TContainer, class TType>
class IteratorCollectionTest
    : public Iterator
{
public:
    virtual int size() { m_collection.size(); }

private:
    TContainer<TType> m_collection;
};


template<typename TItem>
class Set
{
public:
    Set();

    Iterator* createIterator();
    int size();

protected:
    class SetInstance;

private:
    SetInstance*    m_instance;
};

template<typename TItem>
class Set<TItem>::SetInstance
{
public:
    Iterator* createIterator() { return new IteratorCollectionTest<Set, TItem>(); }
    int size() { return  m_vec.size(); }

public:
    std::vector<TItem>  m_vec;
};

template<typename TItem>
Set<TItem>::Set()
    : m_instance(new SetInstance())
{
}

template<typename TItem>
Iterator* Set<TItem>::createIterator()
{
    return m_instance->createIterator();
}

template<typename TItem>
int Set<TItem>::size()
{
    return m_instance->size();
}

int main()
{
    Set<int> m_serr;
    Iterator* iter = m_serr.createIterator();
}

我做错了什么? 有人可以帮助我吗?

Class 模板有一个特殊的成员,叫做injected class name。在 class 模板范围内,模板名称代表 当前专业化 。它不代表模板。

new IteratorCollectionTest<Set, TItem>() 出现在 class 模板 Set 的范围内。所以 MSVC 假定 Set 参数不引用模板。它假定名称指的是 specialization,即 Set<TItem> 的类型。因此在需要模板名称的地方传递了一个 class 名称。

这是 C++98 强制要求的行为。并且此行为已在 C++11 中进行了修改,其中作为模板参数出现的模板名称不引用注入的 class 名称。在 C++11 及更高版本中,GCC 将接受代码。但是当强制使用 C++98 模式时,it complains too.

解决方法是限定名称。

Iterator* createIterator() { return new IteratorCollectionTest<::Set, TItem>(); }

由于 ::Set 是完全限定名称,它只能引用命名空间范围内的模板。