In the following code, the variable number of arguments assume a string variable in itself but it does not happen for string literals
#include <iostream>
#include <string>
#include <memory>
template <typename MyType, typename StringT=std::string, typename... ArgsT,
typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>
std::shared_ptr<MyType> my_function(const StringT& name, ArgsT&&... args) {
std::cout << "name: " << name << std::endl;
auto t = std::make_shared<MyType>(5);
return t;
}
template <typename MyType, typename... ArgsT>
std::shared_ptr<MyType> my_function(ArgsT&&... args) {
auto t = my_function<MyType>("default name", std::forward<ArgsT>(args)...);
return t;
}
int main() {
std::string myvar= "something";
auto ret = my_function<int>("something");
auto ret2 = my_function<int, std::string>(myvar);
auto ret3 = my_function<int>(myvar);
auto ret4 = my_function<int>(42);// 42 could be anything
return 0;
}
Prints:
name: something
name: something
name: default name
name: default name
How to avoid this and call the first constructor in the third my_function<int>(myvar) call as well? How to print "something" in all the cases except the last one?
template <typename MyType, typename... ArgsT>a better match thantemplate <typename MyType, typename StringT=std::string, typename... ArgsT, typename = std::enable_if_t<std::is_constructible_v<std::string, StringT>>>?" Understand that and you should be able to work around it.my_function<int>(myvar)the generic versionmy_function(ArgsT&&... args)is better match because it doesn't require a conversion to const for it's argument. That is, the first overloadmy_function(const StringT& name, ArgsT&&... args)requires a conversion to const for its first parameternameand hence it is worse match than the generic versionmy_function(ArgsT&&... args).