在成员声明中替换模板类类型别名失败



假设您有一个模板化的class,如下所示:

template <typename type>
class Object {
using length_t = unsigned int;

template <length_t length>
void put(type (&)[length]);
};

并且您在其中像这样声明了一个put(...)方法。如何在class之外声明put(...)方法?

  1. 有人可能会采取一种方法:

    /* ERROR: Doesn't match any declarations(?) */
    template <typename type>
    template <typename Object<type>::length_t length>
    void Object<type>::put(type (&)[length]) {}
    

    但这会导致一个特殊的错误

    error: no declaration matches 'void Object<type>::put(type (&)[length])'
    note: candidate is: 
    template <class type>
    template <unsigned int length>
    void Object<type>::put(type (&)[length])
    
  2. 以下是另一种声明put(...)方法以使其工作的方法:

    /* SUCCESS: But `length_t` alias isn't used */
    template <typename type>
    template <unsigned int length>
    void Object<type>::put(type (&)[length]) {}
    

    但是没有使用在CCD_ 7中定义的CCD_。

如何使第一个定义工作,以便在声明中保持class的特性(如类型别名(的使用一致性&定义,还是第二个定义是这里唯一的解决方案?

如何让第一个定义工作,以便在其声明中保持类的特性(如类型别名(的使用一致&定义,

我不得不承认,我不理解这个错误,也不知道如何仅通过更改定义来修复它。错误消息相当令人困惑(您应该将其包含在问题中(。

。。。还是第二个定义是这里唯一的解决方案?

不,不是。如果你同意length_t不作为会员,那么这可能会为你指明正确的方向:

template <template<typename> typename T>
struct length { using type = int; };
template <template<typename> typename T>
using length_t = typename length<T>::type;

template <typename> struct Object;
template <> struct length<Object> { using type = unsigned int; };
template <typename type>
class Object {
//using length_t = unsigned int;

template <length_t<Object> length>
void put(type (&)[length]);
};
template <typename type>
template <length_t<Object> length>
void Object<type>::put(type (&)[length]) {}

CCD_;模板特征";(不确定这个术语是否真的存在(。您不需要将length_t作为Object的成员,而需要为length<Object>提供专门化(这需要Object的前向声明(。int基本情况仅用于说明。如果您愿意,您仍然可以将Object的成员添加到别名length_t<Object>

实时演示

我认为这是一个编译器错误,或者更进一步,是标准中的缺陷。

您的代码实际上没有问题,并且被MSVC接受。如果你把定义放在类中,没有编译器会认为它格式不正确。

我发布了一个与此类似的问题。我得到的结果是,CWG2,这个发布时无人知晓的古老问题,仍然是起草,这意味着定义外的匹配规则甚至是unspecified。这些奇怪的不匹配是因为编译器的实现不同。

然后,为了避免这个问题,首先可以将定义放在类中。如果它依赖于类定义后面定义的东西,而不能在内部定义,则可以:

  1. 使其独立:让using length_t = unsigned int;在外面
  2. 在声明时使其可推导:编译器可能不知道typename Object<type>::length_tlength_t(在类内(是否是同一类型,尽管typename Object<type>::length_t不需要是可推导的。因为在声明的时候,编译器不能确保Object<type>是否被指定,并且使length_t不匹配,在我看来。正如@idclev 463035818所说,template<...> using length_t = unsigned int;将使编译器更容易匹配这个定义

相关内容

  • 没有找到相关文章

最新更新