133

给定一个模板类,如下所示:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

有人如何在头文件中转发声明这个类?

4

4 回答 4

133

你会这样做:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

请注意,默认值在前向声明中,而不是在实际定义中。

于 2012-12-12T20:57:27.617 回答
15

可以声明一个模板化的类,它的定义声明了默认参数,但是任何时候你引用这个类,你必须包含它的所有参数,直到定义被引入。

例如。让我们在std::vector不包括它的情况下使用(的第二个参数std::vector是用默认值定义的):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

然后我们可以在包含向量的情况下使用它,例如:

int main ()
{
    Foo(3);
}

...或者我们可以将它与 一起使用 std::vector,例如:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main ()
{
    Foo(std::vector<int>(3));
}

我没有检查标准,但这适用于clang/gcc最高-std=c++98-std=c++17所以如果它不是正式的标准,那么它看起来是非官方的。

于 2019-12-13T03:42:24.677 回答
8

您只能为模板的第一个声明声明模板的默认参数。如果你想让用户转发声明一个类模板,你应该提供一个转发头。如果您想使用默认值转发声明其他人的类模板,那么您就不走运了!

于 2012-12-12T21:11:48.357 回答
1

我的答案补充了其他答案,因为我发现的解决方案实际上通过在所有参数已知(或作为默认参数提供)时创建一个新类型来减轻对模板类前向声明​​的需求,因此这种新类型,而不是你可以前向声明的,不是不再是模板:

template<typename Type=MyDefault, typename IDType=typename Type::IDType>
class MappingsGeneric
{
...
};

class Mappings : public MappingsGeneric<> {};

然后就可以了class Mappings;。我知道这个解决方案并不适用于任何地方,但它适用于我的用例,因为我只在单元测试上下文中将模板用于非虚拟方法的高性能依赖注入。

于 2021-02-09T18:19:44.210 回答