[英]C++ type alias and forward declaration with default template parameter
我想使用来自第 3 方仅标头库的 span 类实现,但为其使用不同的命名空间。 我几乎所做的是创建新的 span.hpp 代理标头,其中包含库并将其引入新的命名空间。
现在,当尝试包含该代理标头时,我的整个翻译单元编译中断,就好像它在语法上不正确(很多随机错误)
(编辑:我发现了有问题的错误并将其粘贴在最底部):
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>;
}
尝试在没有任何模板参数的情况下实例化 span 时出现错误
提前感谢您的帮助。 :)
干杯
根据规范,这不能按照您希望的方式工作(使用前向声明)。 以后不能using
定义前向声明。 来自 C++11 spec on using-declaration :
由于using-declaration是一个声明,因此在同一声明区域 (3.3) 中对同名声明的限制也适用于using-declarations 。 -- [命名空间.udecl] §7.3.3 ¶13
我认为问题在于类前向声明和使用声明......很明显,这两个声明。
// 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
{
...
}
问题的症结很简单:您不能声明相同的名称来表示两个不同的事物:
给定单个声明区域中的一组声明,每个声明都指定相同的非限定名称,
- 他们都应该指同一个实体...... - [basic.scope.declarative] §3.3.1 ¶4
当您尝试以这种方式同时使用class
和using
时,它们并不指代同一个实体。 因此,这是不允许的。
这个问题的一个可能的解决方案是在你的别名中使用模板参数包:
template <std::size_t... T>
using span = ::old_namespace::span<T...>;
现在span<>
是::old_namespace::span<>
的别名,并且将酌情使用任何默认值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.