Consider a situation where a code uses matricies at many points, so we have defined a typedef
for a matrix type:
#include <cstddef>
template<typename Scalar, size_t size_x, size_t size_y>
class MatrixImpl {};
template<typename T>
using Matrix5x5 = MatrixImpl<T, 5, 5>;
I only add the MatrixImpl
type here to have complete example, but it could also come from an external library or similar.
Now, consider this exemplary function like this:
template<typename Scalar, template<typename> typename MatrixType>
MatrixType<bool> toBool(const MatrixType<Scalar> &) { return MatrixType<bool>{}; }
int main() { Matrix5x5<bool> x = toBool<int, Matrix5x5>(Matrix5x5<int>{}); }
The problem is, that I always have to explicitly specify the template arguments for the function, because the compiler does not consider the using
declaration as a thing to deduce the template arguments.
How can I change that declaration that allow type deduction?
What I want is that the following code would compile without an error:
#include <cstddef>
template<typename Scalar, size_t size_x, size_t size_y>
class MatrixImpl {};
template<typename T>
using Matrix5x5 = MatrixImpl<T, 5, 5>;
template<typename Scalar, template<typename> typename MatrixType>
MatrixType<bool> toBool(const MatrixType<Scalar> &) { return MatrixType<bool>{}; }
int main() { Matrix5x5<bool> x = toBool(Matrix5x5<int>{}); }
Here is the error I'm getting:
main.cpp: In function 'int main()':
main.cpp:11:20: error: no matching function for call to 'toBool(Matrix5x5<int>)'
11 | int main() { toBool(Matrix5x5<int>{}); }
| ~~~~~~^~~~~~~~~~~~~~~~~~
main.cpp:11:20: note: there is 1 candidate
main.cpp:9:18: note: candidate 1: 'template<class Scalar, template<class> class MatrixType> MatrixType<bool> toBool(const MatrixType<Scalar>&)'
9 | MatrixType<bool> toBool(const MatrixType<Scalar> &) {}
| ^~~~~~
main.cpp:9:18: note: template argument deduction/substitution failed:
main.cpp:11:20: note: 'Matrix5x5<int>' {aka 'MatrixImpl<int, 5, 5>'} is not derived from 'const MatrixType<Scalar>'
11 | int main() { toBool(Matrix5x5<int>{}); }
| ~~~~~~^~~~~~~~~~~~~~~~~~
EDIT:
My goal would be that I can call the function without specifying any template arguments, in the same way as it works if the arguments had default values. Similar to this:
This is only added to show that defaults arguments behave the way I want my using
declaration to behave.
#include <cstddef>
template<typename Scalar, size_t size_x=5, size_t size_y=5>
class MatrixImpl {};
template<typename Scalar, template<typename> typename MatrixType>
MatrixType<bool> toBool(const MatrixType<Scalar> &) { return MatrixType<bool>{}; }
int main() { MatrixImpl<bool> x = toBool(MatrixImpl<int>{}); }
From your question, I don't know what MatrixType<bool>
should result in, but here's how you solve the function argument deduction part:
#include <cstddef>
#include <type_traits>
template <typename Scalar, size_t size_x, size_t size_y>
class MatrixImpl {};
template <class T>
using Matrix5x5 = MatrixImpl<T, 5, 5>;
template <template <class, auto...> class MatrixType, class Scalar, auto... Args>
auto toBool(const MatrixType<Scalar, Args...>&) {
return MatrixType<bool, Args...>{};
}
int main() {
auto rv = toBool(Matrix5x5<int>{});
static_assert(std::is_same_v<decltype(rv), MatrixImpl<bool, 5, 5>>);
}