I was creating a Graph program for college, and had created an std::initializer_list
constructor for the graph, like so:
Graph(std::initializer_list< std::string >& _vertices_){
// ... initialising my map of vertices with their names
}
However, when I tried to initialise the Graph in my main program:
int main(){
Graph g = { "A", "B", "C", "D", "F", "G" }; //Error: Does not compile
g.connectEdge( "A", "B" ).setWeight( 2 );
// ... connecting other edges
g.set_path_algorithm( Graph::DJIKSTRA );
int cost = g.find_shortest< Graph::COST >("A", "G");
//int hops = g.find_shortest< Graph::HOPS >("A", "G");
std::cout << "The shortest path between A and G is: " << cost ;
return 0;
}
I get:
test_djikstra.cpp: In function 'int main()':
test_djikstra.cpp:36:46: error: could not convert '{"A", "B", "C", "D", "F", "G"}' from '<brace-enclosed initializer list>' to 'Graph'
Graph g = { "A", "B", "C", "D", "F", "G" };
^
Now, when I create a constructor that takes a std::string
and pass a c-style string
(const char []
), the function to convert it to std::string
is automatically called.
Why does this not convert each const char []
parameter to std::string
?
What is the issue, and what are it's possible solutions?
Edit: So I was creating a reference to a temporary object. Subtle!
Thanks @rafix07
.
This
{ "A", "B", "C", "D", "F", "G" }
creates initializer list object. It is temporary instance. Temporary object cannot be bound to Lvalue reference.
Solutions:
[1] make const reference
Graph(const std::initializer_list< std::string >& _vertices_)
[2] just discard reference
Graph(std::initializer_list< std::string > _vertices_)
Initializer list is lightweight object (can be treated as pair: pointer to data + length), so copying of it is not expensive.