Is it possible to get the compiler to deduce the type for the template function call, using either the type conversion or the deduction guide? And, if not, why not?
#include <iostream>
template<typename T>
class Wrapper
{
public:
Wrapper(T&& elmt)
: m_data(std::forward<T>(elmt))
{ }
const T& data() const
{
return m_data;
}
private:
T m_data;
};
template<typename T>
Wrapper(T&& elmt) -> Wrapper<T>;
template<typename T>
void someFunc(const Wrapper<T>& wrapper)
{
std::cout << wrapper.data() << std::endl;
}
int main()
{
// Any chance this could work?
// someFunc("Make me a Wrapper<const char*> please!"); //fails
// someFunc({"Make me a Wrapper<const char*> please!"}); //fails
// This works, but that's what I'd like to avoid
someFunc(Wrapper{"This one works"});
return 0;
}
(Compiler Explorer link: https://godbolt.org/z/eGs3raMY4)
If Wrapper wasn't a template, this would work directly:
#include <iostream>
class StrWrapper
{
public:
StrWrapper(const char* str)
: m_data(str)
{ }
const char* data() const { return m_data; }
private:
const char* m_data;
};
void strFunc(const StrWrapper& wrapper)
{
std::cout << wrapper.data() << std::endl;
}
int main()
{
strFunc("This works, right?");
return 0;
}
(Compiler Explorer: https://godbolt.org/z/nnoaPcs91)
I know I could add an overload for each type I want the deduction for, but in this case it isn't a very practical solution (many overloads required).
Is it possible to get the compiler to deduce the type for the template function call, using either the type conversion or the deduction guide?
You can do a recursive approach here
// variable template for checking the "Wrapper<T>" type
template<typename T> inline constexpr bool is_Wrapper = false;
template<typename T> inline constexpr bool is_Wrapper<Wrapper<T>> = true;
template<typename T>
void someFunc(T&& arg)
{
if constexpr (is_Wrapper<T>) // if T == Wrapper<T>
std::cout << arg.data() << std::endl;
else // if T != Wrapper<T>, construct explicitly and pass to the someFunc()
someFunc(Wrapper<T>{ std::forward<T>(arg) });
}
This allows the both
someFunc("Make me a Wrapper<const char*> please!"); // works
someFunc(Wrapper{ "This one works" }); // works