模板,其中lambda作为每个实例的唯一默认参数

时间:2019-01-28 21:27:24

标签: c++ templates lambda language-lawyer c++20

我正在寻找一种方法,该方法可在每次实例化模板时自动使默认模板参数唯一。由于由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进行一次扩展。

1 个答案:

答案 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不再起作用 在较新版本的编译器中。