Reputation: 1764
In the following code, how can I make the commented line working in the same way as the line just above of it?
I would like to make it a generic code, that call suitable constructor of a template Type
.
#include <string>
#include <iostream>
template <typename Type>
struct Class
{
Type data;
Class(Type data) : data(data) { }
};
int main()
{
Class<std::string> a = std::string("abc");
// Class<std::string> b = "abc";
std::cout << a.data << std::endl;
return 0;
}
Upvotes: 21
Views: 715
Reputation: 4655
If you are able to change your Class
, you could add a templated converting constructor. Then you'd be able to compile the commented line as written in your example. Notehowever, that it is generally not recommended to use implicit conversions without decent reason as they may result in hard-to-spot bugs (cf the C++ Core Guidlines).
#include <string>
#include <iostream>
template <typename Type>
struct Class
{
Type data;
Class(Type data) : data(data) { }
template<typename Other>
Class(Other other_data) : data(other_data) {}
};
int main()
{
Class<std::string> a = std::string("abc");
Class<std::string> b = "abc";
Class<std::string> c = a;
std::cout << b.data << std::endl;
return 0;
}
If you can use C++14, you could use the std::literals::string_literals::operator""s
and remove the converting constructor. Then, your line would look like this:
using namespace std::literals;
Class<std::string> b = "abc"s;
Live code here.
Upvotes: 2
Reputation: 26302
Class<std::string> b = "abc";
is copy-initialization. It doesn't work because it would involve two user-defined conversions:
const char*
to std::string
,std::string
to Class<std::string>
.But at most one is allowed.
When you write
Class<std::string> b("abc");
// or
Class<std::string> b{"abc"};
you use direct-initialization. It works because now only one user-defined conversion is used:
const char*
to std::string
.Upvotes: 14
Reputation: 32847
Use braced-init-list(or uniform-initiation) to initlize the instance of Class
.
Class<std::string> a{ std::string("abc") }; // works
Class<std::string> b{ "abc" }; // also works
Upvotes: 17