3

I want to make class with variadic wchar* value arguments. Consider the following example.

template<const wchar_t* ...properties>
class my_iterator{
public:
     std::tuple<std::wstring...> get(); // quantity of wstrings depend on quantity of template parameters
};

I want to use that like the following

my_iterator<L"hello", L"world"> inst(object_collection);
while(inst.next()){
    auto x = inst.get();
}

But I receive compile error, when I instantiate the class.

error C2762: 'my_iterator': invalid expression as a template argument for 'properties'

What's wrong and what to do?

Alexey Subbota
  • 938
  • 6
  • 23

3 Answers3

3

This has nothing to do with the template parameter being variadic or non-type - string literals cannot simply be used as template parameters (until P0732 - which was accepted - becomes reality).

template <const char*> struct foo { };
foo<"hi"> x;

Will fail as well. live example on godbolt.org

error: '"hi"' is not a valid template argument for type 'const char*' because string literals can never be used in this context

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
3

What's wrong is [temp.arg.nontype] §2.3. String literals cannot (currently) be used as template arguments. What you could do, for example, is declare named array objects and use those as arguments:

template<const wchar_t* ...properties>
class my_iterator {};


int main()
{
    static constexpr const wchar_t a[] = L"hello";
    static constexpr const wchar_t b[] = L"world";

    my_iterator<a, b> inst;
}

working example here

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
  • Literally did this last week for the same reason. Was a bit annoying. Fortunately shortly thereafter discovered my whole approach was stupid and was able to delete it all, but still... ;) – Lightness Races in Orbit Sep 12 '18 at 13:38
  • 1
    Yeah, personally I would just try to keep strings out of my template stuffs. But if you must, the above would seem to be the simplest solution for the particular problem at the moment. And it's kinda forward-compatible, assuming we will eventually be able to pass string literals as template arguments… – Michael Kenzel Sep 12 '18 at 13:51
  • 2
    Note, that template will be parametrized by pointers, i.e. their addresses, and not their contents. So if you write the same code in different function (i.e. using different instances of `a` and `b`) you'll get different template instantiation. – Dan M. Sep 12 '18 at 16:06
2

Another alternative is to pass the characters one by one,

#include <tuple>

template<wchar_t ...properties>
class my_iterator{
public:
     std::tuple<decltype(properties)...> get(); // quantity of wstrings depend on quantity of template parameters
};

my_iterator<L'h', L'e',  L'l', L'l', L'o'> inst;
amin
  • 3,672
  • 5
  • 33
  • 61