【问题标题】:Forward declaration obscuring ancestor template parameter from nested template前向声明掩盖了嵌套模板中的祖先模板参数
【发布时间】:2012-06-19 19:12:16
【问题描述】:

编辑:代码已被精简,只包含重现错误所需的内容。错误发生在const V * Resolve(const Resource<T> *);,是error C2923: 'Resource' : 'T' is not a valid template type argument for parameter 'T'

我正在使用 MSVC++ 2010 Express 编译本文末尾显示的代码,但出现以下错误:

1>test.cpp(119): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>          test.cpp(121) : see reference to class template instantiation 'Resource<T>::Api<U>::ContainerDerived<V>' being compiled
1>          test.cpp(136) : see reference to class template instantiation 'Resource<T>::Api<U>' being compiled
1>          test.cpp(143) : see reference to class template instantiation 'Resource<T>' being compiled
1>test.cpp(119): error C2143: syntax error : missing ',' before '&'
1>test.cpp(120): error C2923: 'Resource' : 'T' is not a valid template type argument for parameter 'T'

(代码中的第 119 行是这样的:std::auto_ptr&lt;Dependent&lt;V&gt; &gt; Construct(const T &amp;);

似乎前向声明template &lt;typename V&gt; class ContainerDerived; 导致ContainerDerived 的定义失去了祖先类Resource&lt;T&gt; 中T 参数的“可见性”。

这是我尝试过的:

  • 切换Dependent&lt;V&gt;ContainerDerived&lt;V&gt;的定义顺序(让后者先出现),将前向声明改为template &lt;typename V&gt; class Dependent;。这可以修复 ContainerDerived,但会导致 Dependent 出现同样的问题。
  • 在任一定义之前添加typedef T FooBar;,并在Dependent/ContainerDerived 中的一个/两个中将所有“T”实例切换为“FooBar”。这可以编译,但不会发生“T”和“V”为同一类型时的预期特化。

基本上,添加某事物的前向声明似乎会从其定义中掩盖 T 参数。有人知道为什么会这样吗?

代码如下:

#include <memory>

template <typename TypeContainer, typename TypeContained>
class Proxy
{
public:
    class Container {};

    Proxy(TypeContainer * = NULL);
    Proxy(Proxy &);
    ~Proxy();
};

struct Dummy {};

template <typename T>
class Resource : public T, public Proxy<Resource<T>, Dummy>::Container
{
public:

    template <typename U>
    class Api
    {
    public:

        template <typename V> class ContainerDerived;

        template <typename V>
        class Dependent : public Proxy<ContainerDerived<V>, Dependent<V> > {};

        template <typename V>
        class ContainerDerived
        {
        public:
            const V * Resolve(const Resource<T> *);
        };

    };
};

【问题讨论】:

  • 有机会制作更小的复制品吗?
  • 我编辑了 OP。请记住,它已被剥夺了生成错误所必需的所有内容。
  • 目前还不能确定这是否是编译器错误,但很好奇:如果您使用注入的类名而不是模板 ID,如 const V * Resolve(const Resource*); 中那样,是否有效?
  • 它可以工作,但我在精简版中删除的方法之一采用 'T &' 作为参数:std::auto_ptr&lt;Dependent&lt;V&gt;&gt; Construct(const T &amp; refResource)

标签: c++ visual-studio-2010 templates visual-c++


【解决方案1】:

这些关系相当复杂。在主要问题中,您必须使用 typename 前面的依赖名称。

template <typename V>
class ContainerDerived : public ContainerBase<ContainerDerived<V>, Dependent<V> >
{
public:
        typedef typename Api::Dependant<V> DV;
        typedef typename Resource::T TX;
    std::auto_ptr<DV> Construct(const TX &);
        typedef Resource<typename Resource::T> TR;
    const V * Resolve(const TR *);
};

【讨论】:

  • 我认为声明 T 的 typedef 并在 DependentContainerDerived 中使用该 typedef 已经解决了这个问题。我不能确定,因为我有other compilation problems。无论如何,我不明白为什么需要 typedef。 T 应该对 Resource&lt;T&gt; 声明中的所有内容可见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
相关资源
最近更新 更多