18
votes

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);
}
2
In GCC it's a bug, in that it think you declare a function. - Some programmer dude
@Someprogrammerdude I'm not sure if it is a correct syntax though - there is no corresponding example in the standard yet it mentions the situation... - W.F.
The nested template deduction guide works if the parent class is not templated.... - AndyG
@AndyG yep the syntax seems to be correct - W.F.

2 Answers

16
votes

[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).

1
votes

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"};
}