How to provide deduction guide for nested template class?

2.2k views Asked by At

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

There are 2 answers

4
Barry On BEST ANSWER

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

0
Guss On

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