I'd like to see if it is possible (though I have a feeling it is not) whether it is possible to apply uniform types based on the first template argument given. For example:
template <class T>
void foo(T, T) {}
int main() {
// deduced as int
foo(1, 1);
// deduced as double
foo(1.0, 1.0);
// not deducible, will error.
//foo(1.0, 1);
return 0;
}
Is there some technique which will allow me to force the second parameter of foo to be exactly the first? I do realize that the canonical solution, albeit slightly more verbose would be foo<double>(1.0, 1)
.
That being said I'd like to be able to execute foo(1.0, 1)
which would force the second parameter type as the first, and upcast 1 to 1.0.
Additionally, foo(1, 1.0)
would fail because the first parameter sets foo
to foo<int>
, and as such the second parameter could not be downcast to an int.
Finally, I'd like to be able to do this without recursive templatization, as I'd like to apply this technique to object constructors.
Just make uses of the template parameter in function parameters after the first into "non-deducible contexts":
template <typename T>
struct type_identity {
using type = T;
};
template <typename T>
using type_identity_t = typename type_identity<T>::type;
template <class T>
void foo(T, type_identity_t<T>) {}
Now foo(1.0, 1)
means the same as foo<double>(1.0, 1)
, and the function specialization has arguments (double, double)
so the 1
is implicitly converted from int
to double
. And the other way around, foo(1, 1.0)
means foo<int>(1, 1.0)
and the 1.0
is implicitly converted to int
.