How can I prevent user from specifying a function template parameter, forcing it to be deduced?
What about making fancy_cast
a variable template?
template <typename A>
struct fancy_cast_t {
template <typename B>
A operator()(B x) const { return x; }
};
template <typename A>
constexpr fancy_cast_t<A> fancy_cast {};
fancy_cast<int>(1.5); // works
fancy_cast<int, int>(1.5); // doesn't work
fancy_cast<int>.operator()<int>(1.5); // works, but no one would do this
This is not the most efficient solution, but you can create a class that has a template parameter for the type to convert to, and then have a constructor template that takes any type. Then if you add an operator T
for the type you instantiate the class with you can have that return correct value. That would look like
template<typename T>
struct fancy_cast
{
T ret;
template<typename U>
fancy_cast(U u) : ret(u) {} // or whatever you want to do to convert U to T
operator T() && { return std::move(ret); }
};
int main()
{
double a = 0;
int b = fancy_cast<int>(a);
}
This works because there is no way to specify the template parameter for the constructor since you can't actually call it.
I found a good-looking solution.
We can use a non-type parameter pack, of a type that the user can't construct.1 E.g. a reference to a hidden class:
namespace impl
{
class require_deduction_helper
{
protected:
constexpr require_deduction_helper() {}
};
}
using require_deduction = impl::require_deduction_helper &;
template <typename A, require_deduction..., typename B>
A fancy_cast(B)
{
return {};
}
1 We do have to leave a loophole for constructing a deduction_barrier
, otherwise the code would be ill-formed NDR. That's why the constructor is protected.