如何为嵌套模板类提供扣除指南?

17
根据[temp.deduct.guide/3]:

(...) 在与对应的类模板相同的作用域内声明一个引导式推断,并且对于成员类模板,访问权限也相同。 (...)

但是下面的例子在[gcc][clang]中似乎都无法编译。
#include <string>

template <class>
struct Foo {
    template <class T>
    struct Bar {
        Bar(T) { }
    };
    Bar(char const*) -> Bar<std::string>;
};

int main() {
    Foo<int>::Bar bar("abc");
    static_cast<void>(bar);
}

什么是嵌套模板类的正确推导指南语法?或者这个语法是正确的,但编译器还没有支持它?


类似的语法但不涉及嵌套类,在gcc和clang中都可以编译通过:

#include <string>

template <class T>
struct Bar {
    Bar(T) { }
};
Bar(char const*) -> Bar<std::string>;

int main() {
    Bar bar("abc");
    static_cast<void>(bar);
}

在GCC中,这是一个错误,它认为你在声明一个函数。 - Some programmer dude
@Someprogrammerdude 我不确定它是否是正确的语法 - 标准中没有相应的示例,但它提到了这种情况... - W.F.
嵌套的模板推导指南仅在父类未被模板化时起作用... - AndyG
@AndyG 是的,语法似乎是正确的。 - W.F.
2个回答

15

[temp.deduct.guide]中包含以下句子:

一个类型推断指南应在相应类模板的同一作用域中声明,并且对于成员类模板,应具有相同的访问权限。

这表明您的示例应该可以工作 - 对于成员类模板,类型推断指南得到了显式支持,只要它们在相同的作用域和访问权限(也就是类作用域和public)中声明即可。请检查是否满足这些条件。

这是gcc bug 79501(由Richard Smith提交)。


2
@W.F. 您的外部类是一个类模板,这个错误中的示例更简单。应该提交一个 LLVM 错误报告。 - Barry
是的,这绝对表明语法应该是正确的。我会尝试提交一个错误报告... - W.F.
4
刚刚提交了llvm bug 34520 - W.F.
根据Richard的说法,这是一个缺陷。请参见PR35107上的评论#1。 - Rakete1111

1
如果你真的需要一个临时的快速解决方法,考虑使用特定于编译器的指令。 此处,在godbolt上 关键是通过添加特定于编译器的指令来处理GCC和Clang之间的行为分歧。这种方法并不是最优解,但如果你在项目中受阻,它可能会帮助你等待编译器的补丁。
请参见我对此帖子的回答:https://dev59.com/JcDqa4cB1Zd3GeqPTwLm#66888013
#include <string>

template <class>
struct Foo {
    template <class T>
    struct Bar {
        Bar(T) { }
    };
    #if __clang__
    Bar(char const*) -> Bar<std::string>;
    #endif
};

void instanciate_symbols()
{
    [[maybe_unused]] auto bar = Foo<int>::Bar{"abc"};
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接