I have this code
#include <unistd.h>
#include <vector>
#include <iostream>
using namespace std;
std::string join(std::vector<std::variant<std::string, std::string_view>> input) {
return "";
}
int main(int argc, char* argv[]) {
string a = "hello";
string_view b = "world";
cout<<join(std::vector({a,b}))<<endl; // this returns error
vector<std::variant<string, string_view>> v;
v.push_back(a);
v.push_back(b);
cout<<join(v)<<endl; // this works
return 0;
}
I get the following error
candidate template ignored: deduced conflicting types for parameter '_Tp' ('string' (aka 'basic_string<char>') vs. 'string_view' (aka 'basic_string_view<char>'))
vector(initializer_list<value_type> __il);
My understanding is that when I am doing std::vector({a,b})
, its assuming the vector will have same types for all arguments which is understandable.
How to make it work with that std::vector({a,b})
? How can I change the join()
function or its just not possible because the failure itself is at construction of vector?
As mentioned in a comment, when the compiler sees std::vector({a, b})
it will try to deduce the template argument for std::vector
, via CTAD, but a
and b
have conflicting types, so the deduction fails, as the error message is telling you.
There's no reason why, because they are different, the compilier should deduce the template argument is a std::variant
. Think about it: what if I had defined, in your code, another type, such as
struct Foo {
Foo(std::string);
Foo(std::string_view);
};
This type, just like std::variant<std::string, std::string_view>
, can be constructed from std::string
and std::string_view
. Should the compiler have deduced you wanted a std::vector<Foo>
?
Not to mention std::any
, that can be constructed almost from everything. Should the compiler have deduced you wanted std::vector<std::any>
?
CTAD deduces template parameters from the arguments you pass to the class constructor, but it can't randomly pick conversions like the one you expect, so you have to be explicit:
using VS = std::variant<std::string, std::string_view>;
// ...
cout<<join(std::vector<VS>({a,b}))<<endl;