1

The following sample code does compiles in VC++ 2019, clang++ and g++ but not VC++ 2015.

namespace ns
{
    template<const char* str>
    struct Foo
    {
    };
    
    static const char name[] = "Test";
    Foo<name> foo;
}

int main()
{
}

Are there any workarounds for VC++ 2015? I'm assuming the code is conforming but VC++ 2015 had a bug which was fixed in VC++ 2019. I'd migrate to VC++ 2019 but my company builds in VC++ 2015.

Olumide
  • 5,397
  • 10
  • 55
  • 104
  • 1
    Your company should upgrade to VC 2019. VC2015 is really outdated. Your code is C++11 compliant but I think VC2015 only supports only C++03, maybe this helps: https://stackoverflow.com/questions/30506769/using-std-c11-on-vs2015 – Jabberwocky Nov 02 '20 at 11:18

2 Answers2

1

As mentioned in the comments, the issue lies with the fact that VS-2015 does not comply with the C++11 Standard, which is required to implement the code you have shown.

Looking at how the issue is described in this report, the only way I have found to resolve the issue is to remove both the static and const qualifiers in your declaration of name. The following compiles even with the VS-2010 build tools (I don't have access to the VS-2015 tools on my PC but, as this works with both VS-2010 and VS-2019, I assume it would also be OK in VS-2015).

namespace ns {
    template<const char* str>
    struct Foo {
    };

    char name[] = "Test"; // Adding either "static" or "const" causes C2970
    Foo<name> foo;
}

int main()
{
}

Whether or not this workaround is suitable for your needs remains to be seen.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
1

MSVC 2015 doesn't fully support C++11, and non-type template arguments with internal linkage is an example of a C++11 feature which VC++ didn't support until version 14.14 (VS 2017 15.8).

I can think of 3 solutions:

  • Don't use template arguments with internal linkage by removing static const specifiers from char name[]
  • Upgrade the compiler to VC++ 14.20+ (MSVC 2019)
  • Use feature detection and/or conditional compilation

Regarding conditional compilation, it can be achieved like this:

#if !defined(_MSC_VER) || _MSC_VER > 1914 // this part can be in a global config.h
#  define INTERNAL static const
#else
#  define INTERNAL 
#endif

namespace ns
{
    template<const char* str>
    struct Foo
    {};
    
    INTERNAL char name[] = "Test";
    Foo<name> foo;
}

int main()
{
}
rustyx
  • 80,671
  • 25
  • 200
  • 267
  • Awesome! BTW, unless I've misunderstood you, I am certain that templates that accept `static const char[]` as non-type parameters predates C++11. – Olumide Nov 02 '20 at 13:33
  • 1
    Template args with *internal* linkage are a C++11 feature. Try compiling with [`-std=c++03`](https://gcc.godbolt.org/z/1ooev1) for example. Clang will issue a warning and GCC won't accept the code at all. – rustyx Nov 02 '20 at 13:48