我正在寻找一种方法,该方法可在每次实例化模板时自动使默认模板参数唯一。由于由lambda表达式创建的未命名函数对象具有不同的类型,因此我想到以某种方式采用它们。随着标准daft的最新更改删除了“ lambda表达式不应出现在...模板参数中” 限制(请参见Wording for lambdas in unevaluated contexts),这似乎是个好主意。因此,我写了以下compiles on recent gcc and clang的有效片段:
#include <type_traits>
template<void ( * ) (void) = [](){}> class
unique final {};
static_assert(false == ::std::is_same_v<unique<>, unique<>>);
int main()
{
return 0;
}
这是可行的方法还是“病态,不需要诊断”的情况之一?
一些其他上下文:我想用它来实现Ada样式的强类型定义,该定义应在单个翻译单元中工作,而无需手动发明否则会不使用的唯一标记:
struct _tag_WowInt {};
using Int = type<int, _tag_WowInt>;
struct _tag_SoUnique {};
using DifferentInt = type<int, _tag_SoUnique>;
Upd1:我想提一下,涉及__COUNTER__
或类似宏的方法在一般情况下将不起作用,因为它们只能由预处理器和won't yield unique types when used inside of template for example进行一次扩展。
答案 0 :(得分:1)
我相信您是对的,在我看来,这是“格式错误,无需诊断”。我认为这涵盖了 [temp.res/8.4]和[temp.res/8.5]:
(8.4)―紧随模板定义之后的假想实例化将由于以下原因而形成错误 不依赖模板参数的构造,或者
(8.5)―在假设实例化中对此类构造的解释与解释的不同 模板的任何实际实例中对应结构的构造。 [注意:在以下情况下可能会发生这种情况:
(8.5.1)―非依赖性名称中使用的类型在定义模板时是不完整的,但在执行实例化时是完整的,或者
(8.5.2)―在模板定义中对名称的查找找到了using-声明,但是在实例化中相应范围内的查找未找到任何声明,因为using-declaration是一个包扩展,并且包是空的,或者
(8.5.3)―实例化使用在定义模板时尚未定义的默认参数或默认模板参数,或者
(8.5.4)―模板实例化中的常量表达式求值使用
(8.5.4.1)―整数或无作用域枚举类型的const对象的值或
(8.5.4.2)― constexpr对象或
的值(8.5.4.3)―引用或
的值(8.5.4.4)― constexpr函数的定义, 并且在定义模板时未定义该实体,或者
(8.5.5)―模板使用由非依赖的simple-template-id指定的类模板专业化或变量模板专业化,或者从在以下情况下未定义的部分专业化实例化模板已定义,或它命名了在定义模板时未声明的显式专门化名称。 — 尾注]
即使注释的示例中未明确列出您的用例,但据我所知,该要求意味着unique<>
在整个程序中必须引用相同的内容,否则格式错误,不需要诊断。
这是CWG1850。委员会似乎不喜欢这个
有状态的元编程。 constexpr
counter不再起作用
在较新版本的编译器中。