wouldnotliketo
wouldnotliketo

Reputation: 323

Cast from type parametrized by const template argument to non-const template argument

I have a class with variadic template parameters:

template<typename... Args>
class something {
public:
  something(Args&&... args); // omitted for brevity
}

I have a function that accepts a list of arguments and returns an object of this class:

template<typename... Args>
auto make_something(Args&&... args) {
    return something<Args...>(std::forward<Args>(args)...);
}

If I call it like so:

something<int, std::string> s = make_something<int, std::string>(1, "");

it compiles and works fine.

but if I try to pass a const argument, I get compile errors:

const std::string t = "";
something<int, std::string> s1 = make_something(1, t); // no viable conversion from something<... const basic_string<char>> to something<... std::string>

How can I successfully pass const and then, idk, cast the result to the requested type, parametrized by a non-const type?

I suspect it has something to do with the type of the object I'm returning but I don't actually know what to replace auto with in this case.

Upvotes: 0

Views: 64

Answers (2)

Caleth
Caleth

Reputation: 62694

There are two options, depending on if you really want to have something<int, const std::string &> be a type that make_something(1, t) returns.

If that is the case, you can have a converting constructor

template<typename... Args>
class something {
public:
  something(Args&&... args); // omitted for brevity
  template<typename... OtherArgs> 
  something(something<OtherArgs...>); // convert each OtherArgs into Args
}

In the alternative, where you want make_something(1, t) to result in something<int, std::string>

template<typename... Args>
class something {
public:
  template<typename... OtherArgs> 
  something(OtherArgs&&...); // use each OtherArgs for Args
}

template <typename... Args>
auto make_something(Args&&... args)
{
    return something<std::decay_t<Args>...>(std::forward<Args>(args)...);
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 217275

You might do (if relevant):

template <typename... Args>
auto make_something(Args&&... args)
{
    return something<std::decay_t<Args>...>(std::forward<Args>(args)...);
}

So you got something<int, std::string> instead of something<int, const std::string&>

Upvotes: 2

Related Questions