17

According to [temp.deduct.guide/3]:

(...) A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access. (...)

But below example doesn't seem to compile in both [gcc] and [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);
}

What is the correct syntax of deduction guide for nested template class? Or maybe this one is correct but it isn't yet supported by the compilers?


Similar syntax but without nested class compiles fine both in gcc and 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);
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
W.F.
  • 13,888
  • 2
  • 34
  • 81

2 Answers2

15

[temp.deduct.guide] includes the sentence:

A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access.

This suggests that your example should work - deduction guides are explicitly supported for member class templates, as long as they're declared in the same scope and access (which would be the class scope and public - check and check).

This is gcc bug 79501 (filed by Richard Smith).

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 2
    @W.F. Your outer class is a class template, the example in this bug is simpler. Should file an llvm bug. – Barry Sep 07 '17 at 19:27
  • Yep this definitely suggests that the syntax should be correct. I'll try to file a bug then... – W.F. Sep 07 '17 at 19:31
  • 4
    Just filed [llvm bug 34520](https://bugs.llvm.org/show_bug.cgi?id=34520) – W.F. Sep 07 '17 at 19:44
  • According to Richard, this is a defect. See comment #1 on [PR35107](https://llvm.org/pr35107). – Rakete1111 Nov 09 '17 at 16:51
1

If you really need a temporary quick-fix, consider using compiler-specific instructions.

Here, on godbolt

The key is to handle the behavioral divergence between GCC and Clang by adding a compiler-specific directive.
This is way sub-optimal, but if you are blocked in your project, it may help you wait for compiler(s) patch.

See my answer to this post : https://stackoverflow.com/a/66888013/10883423

#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"};
}
Guss
  • 762
  • 4
  • 20