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

标签 c++

我想使用仅来自第三方 header 库的span类实现,但是要使用不同的命名空间。我几乎所做的就是创建新的span.hpp代理 header ,其中包括库并将其引入新的 namespace 。

现在,当尝试包含该代理 header 时,我的整个翻译单元编译会中断,好像它在语法上是不正确的(很多随机错误)

(编辑:我发现了有问题的错误并将其粘贴在最底部):

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>;

}

在简单地编写代码一点之后,它就可以正常工作:
namespace new_namespace
{

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

我的问题是-说我真的很想继续使用默认模板参数和类型别名分开声明。在这种情况下,我该如何实现?

编辑:

有问题的错误是:
/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;

那么两者都被视为声明?到底发生了什么事,它们之间有何冲突?

还有一点,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
{
   ...
}

}

为什么using别名不从原始类中查找默认模板参数?如果我尝试省略默认参数,例如简单地写:
namespace new_namespace
{
   template <std::size_t Value> // no default parameter provided
   using span = ::old_namespace::span<Value>;
}

尝试实例化没有任何模板参数的跨度时出现错误

预先感谢您的帮助。 :)

干杯

最佳答案

根据规范,这不能按您希望的方式(带有前向声明)工作。以后不能通过using定义前向声明。从C++ 11规范中使用声明:

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. -- [namespace.udecl] §7.3.3 ¶13



我认为问题在于类正向声明和using-声明是……很显然,这两个声明。
// 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>;

在您给出的示例中,该示例仅适用于class,您没有两个声明-您有一个前向声明和一个定义(如果尚未声明,则意味着声明):
// Forward declaration.
template <typename Value = dynamic_extent>
class span;

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

问题的症结很简单:您不能声明相同的名称来表示两种不同的含义:

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


当您尝试以这种方式一起使用classusing时,它们不会引用同一实体。因此,这是不允许的。

此问题的可能解决方案是在别名中使用模板参数包:
template <std::size_t... T>
using span = ::old_namespace::span<T...>;

现在,span<>::old_namespace::span<>的别名,并且将适当使用所有默认值。

关于c++ - 具有默认模板参数的C++类型别名和前向声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59897907/

相关文章:

c++ - 链表与 C++ 和通用模板给出段错误。

使用调度程序的 C++ NTOH 转换 - 事件队列

c++ - 使用 C 生成不重复的随机数列表?

c++ - 如何在 GUI 应用程序中封装控制台 exe 文件?

c++ - 与旧 C/C++ 代码向后兼容的 C++ 派生?

c++ - 构建对象数组是如何工作的?我坚持这个例子

c++ - 当参数是目录时,Ifstream open() 不设置错误位

c++ - 对 push_front 属性有点困惑。 intList.push_front(2 * intList.back()) 究竟会做什么?

c++ - 尽可能小地从 Boost 中提取 sublib

c++ - 具有前向声明的转换运算符