模板与lambda作为每个实例化的唯一默认参数

use*_*670 12 c++ lambda templates language-lawyer c++20

我正在寻找一种方法来自动使默认模板参数在每次实例化模板时都是唯一的.由于lambda表达式创建的未命名函数对象具有不同的类型,我想以某种方式采用它们.随着标准愚蠢删除的最近更改"一个lambda表达式不会出现在......模板参数中"限制(参见未评估上下文中的lambdas的措辞),这似乎是一个好主意.所以我编写了以下有点编写最近gcc和clang的工作片段:

#include <type_traits>

template<void ( * ) (void) = [](){}> class
unique final {};

static_assert(false == ::std::is_same_v<unique<>, unique<>>);

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是一种可行的方法还是其中一种"形成不良,无需诊断"的案例?

一些额外的上下文:我想使用它来实现Ada样式的强类型定义,这些定义应该在单个翻译单元中工作,而无需手动发明未使用的唯一标记:

struct _tag_WowInt {};
using Int = type<int, _tag_WowInt>;
struct _tag_SoUnique {};
using DifferentInt = type<int, _tag_SoUnique>;
Run Code Online (Sandbox Code Playgroud)

Upd1:我想提一下,涉及__COUNTER__或类似宏的方法在一般情况下不起作用,因为它们只会被预处理器扩展一次,并且在模板内部使用时不会产生唯一类型.

met*_*fox 2

我相信你是对的,在我看来这是“格式错误,不需要诊断”。我认为\n [temp.res/8.4][temp.res/8.5]涵盖了这一点:

\n\n
\n

(8.4) \xe2\x80\x95 由于不依赖于模板参数的构造,紧随其定义的模板的假设实例化将是格式错误的,或者

\n\n

(8.5) \xe2\x80\x95 假设实例化中此类构造的解释不同于模板的任何实际实例化中相应构造的解释。[笔记:这可能发生在以下情况下:

\n\n

(8.5.1) \xe2\x80\x95 非依赖名称中使用的类型在定义模板时不完整,但在执行实例化时完整,或者

\n\n

(8.5.2) \xe2\x80\x95 在模板定义中查找名称找到了 using 声明,但在实例化中相应范围中的查找没有找到任何声明,因为 using 声明是包扩展,并且相应的包是空的,或者

\n\n

(8.5.3) \xe2\x80\x95 实例化使用在定义模板时尚未定义的默认参数或默认模板参数,或者

\n\n

(8.5.4) 模板实例化中的 \xe2\x80\x95 常量表达式求值使用

\n\n

(8.5.4.1) \xe2\x80\x95 整型或无作用域枚举类型的 const 对象的值或

\n\n

(8.5.4.2) \xe2\x80\x95 constexpr 对象的值或

\n\n

(8.5.4.3) \xe2\x80\x95 参考值或

\n\n

(8.5.4.4) \xe2\x80\x95 constexpr 函数的定义,\n 并且在定义模板时未定义该实体,或者

\n\n

(8.5.5) \xe2\x80\x95 模板使用由非依赖 simple-template-id 指定的类模板特化或变量模板特化,并且它是从非依赖的部分特化实例化的在定义模板时定义,或者它命名了在定义模板时未声明的显式专业化。\n \xe2\x80\x94\xe2\x80\x89尾注]

\n
\n\n

尽管您的用例没有在注释的示例中明确列出,但根据我的理解,该要求意味着unique<>必须在整个程序中引用相同的事物,否则它的格式不正确,不需要诊断。

\n\n

这是CWG1850。委员会似乎不喜欢这种有状态的元编程。柜台constexpr起作用。

\n

  • @Rakete1111 我明白了。这使得疯狂的事情变得可能:https://wandbox.org/permlink/ACtX4SdSJqc2MOHz (3认同)