Class template with templated non-type parameter not compiling with separate implementation header

Viewed 59

I have a fixed string implementation with a deduction guide like so:

// FixedString.hpp

template <size_t N>
struct FixedString
{
    char chars[N+1] = {};

    constexpr FixedString (const char (&str)[N+1])
    { 
        std::copy_n(str, N+1, chars);
    }
};

template <size_t N>
FixedString (const char (&str)[N]) -> FixedString<N-1>;

I also have a class that takes my FixedString type (with no defined size) as a template parameter:

// Foo.hpp

#include "FixedString.hpp"

template <FixedString TName>
class Foo
{
public:
    Foo ();
};

#include "Foo.impl.hpp"

... and a using declaration in some other file:

// OtherFile.hpp

using Bar_t = Foo<"bar">;

When I implement the constructor of Foo inside of Foo.hpp, everything works fine. But when I try to implement the constructor in a separate included header, like so:

// Foo.impl.hpp

#include "Foo.hpp"

template <FixedString TName>
Foo<TName>::Foo ()
{}

I get the following errors:

  • class template argument deduction failed
  • no matching function for call to 'FixedString(FixedString<...auto...>)'
  • conflicting declaration of template 'template<FixedString<...auto...> TName> int Foo()'

And the same goes for any method I try to implement outside of the main Foo class header.

So here is my question: is there anyway for me to separate the implementation from the declaration without specifying a hardcoded size for my fixed strings?

Am I forced into a single header approach here if I want my FixedString type to deduce the size automatically?

1 Answers

For posterity:

Turns out this is absolutely valid C++20 code (thanks @AndyG), but versions of clang lower than 12.0.0 and versions of gcc lower than 10.3 fail to compile.

Here's a link to an example where you can verify this (thanks again @AndyG): https://godbolt.org/z/GoTfd3bjv

Related