简体   繁体   English

C++ 类型别名和带有默认模板参数的前向声明

[英]C++ type alias and forward declaration with default template parameter

I wanna use span class implementation from 3rd party header-only library, but use different namespace for it.我想使用来自第 3 方仅标头库的 span 类实现,但为其使用不同的命名空间。 What I pretty much did is create new span.hpp proxy header which includes library and introduces it to new namespace.我几乎所做的是创建新的 span.hpp 代理标头,其中包含库并将其引入新的命名空间。

Now, when trying to include that proxy header, my whole translation unit compilation breaks as if it was syntatically incorrect (lots and lots of random errors)现在,当尝试包含该代理标头时,我的整个翻译单元编译中断,就好像它在语法上不正确(很多随机错误)

(EDIT: I found the error in question and pasted it at the very bottom): (编辑:我发现了有问题的错误并将其粘贴在最底部):

namespace new_namespace
{

   template <std::size_t Value = ::old_namespace::dynamic_extent>
   class span;

   template <std::size_t Value>
   using span = ::old_namespace::span<Value>;

}

After simplyfying code a little bit it works just fine:在简单地修改代码后,它工作得很好:

namespace new_namespace
{

   template <std::size_t Value = ::old_namespace::dynamic_extent>
   using span = ::old_namespace::span<Value>;
}

My question is - say I really, really wanna keep forward declaration with default template parameter and type alias separate.我的问题是 - 说我真的,真的想保留默认模板参数和类型别名分开的前向声明。 How do I achieve this in this scenario?在这种情况下我该如何实现?

Edit:编辑:

The error in question is:有问题的错误是:

/span.hpp:12:46: error: conflicting declaration of template 'template<long unsigned int Value> using span = old_namespace::span<T>'

 using span = ::old_namespace::span<Value>;
                                          ^
/span.hpp:9:7: note: previous declaration 'template<long unsigned int Value> class new_namespace::span'

 class span;

So both are treated as declarations?所以两者都被视为声明? What is going on here exactly and how are they conflicting?这里到底发生了什么,它们是如何冲突的?

One more thing, the definition of old_namespace::span provides a default value for template parameter Value in the form of:还有一点,old_namespace::span 的定义为模板参数 Value 提供了一个默认值,形式为:

namespace old_namespace
{

template <typename Value = dynamic_extent> // Default parameter in forward declaration
class span;

template <typename Value> // No default parameter here
class span
{
   ...
}

}

Why isn't using alias looking for default template parameters from original class?为什么不using别名从原始类中查找默认模板参数? If I try to omit default parameter eg simply writing:如果我尝试省略默认参数,例如简单地写:

namespace new_namespace
{
   template <std::size_t Value> // no default parameter provided
   using span = ::old_namespace::span<Value>;
}

I get error when trying to instantiate span without any template parameters尝试在没有任何模板参数的情况下实例化 span 时出现错误

Thanks for help in advance.提前感谢您的帮助。 :) :)

Cheers干杯

This cannot work the way you want it to (with a forward declaration) according to the spec.根据规范,这不能按照您希望的方式工作(使用前向声明)。 A forward declaration cannot be defined later by using .以后不能using定义前向声明。 From the C++11 spec on using-declaration :来自 C++11 spec on using-declaration

Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region (3.3) also apply to using-declarations .由于using-declaration是一个声明,因此在同一声明区域 (3.3) 中对同名声明的限制也适用于using-declarations -- [namespace.udecl] §7.3.3 ¶13 -- [命名空间.udecl] §7.3.3 ¶13

I believe the problem to be that a class forward declaration and a using-declaration are... rather obviously, both declarations .我认为问题在于类前向声明和使用声明......很明显,这两个声明

// Declares span as a template class.
template <std::size_t Value = ::old_namespace::dynamic_extent>
class span;

// Attempts to redeclare span as something else -- this is invalid.
template <std::size_t Value>
using span = ::old_namespace::span<Value>;

In the example you've given where this works with only class , you do not have two declarations -- you have a forward declaration and a definition (which implies declaration if not already declared ):在您给出的仅适用于class的示例中,您没有两个声明 - 您有一个前向声明和一个定义如果尚未声明,则意味着声明):

// Forward declaration.
template <typename Value = dynamic_extent>
class span;

// Definition, which agrees with the forward declaration -- no error.
template <typename Value>
class span
{
   ...
}

The crux of the issue is rather straightforward: you can't declare the same name to mean two different things:问题的症结很简单:您不能声明相同的名称来表示两个不同的事物:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,给定单个声明区域中的一组声明,每个声明都指定相同的非限定名称,

  • they shall all refer to the same entity... -- [basic.scope.declarative] §3.3.1 ¶4他们都应该指同一个实体...... - [basic.scope.declarative] §3.3.1 ¶4

When you try to use class and using together in this way, they do not refer to the same entity.当您尝试以这种方式同时使用classusing时,它们并不指代同一个实体。 Therefore, this is not allowed.因此,这是不允许的。


A possible solution this problem is to use template parameter packs in your aliases:这个问题的一个可能的解决方案是在你的别名中使用模板参数包:

template <std::size_t... T>
using span = ::old_namespace::span<T...>;

Now span<> is an alias for ::old_namespace::span<> , and any defaults will be used as appropriate.现在span<>::old_namespace::span<>的别名,并且将酌情使用任何默认值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM