Reputation: 485
I was looking at this file in the Pytorch repo: https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/native/quantized/cpu/conv_packed_params.h
#pragma once
#include <ATen/ATen.h>
#include <ATen/core/ivalue.h>
template <int kSpatialDim = 2>
struct ConvPackedParamsBase : public torch::jit::CustomClassHolder {
virtual at::Tensor apply(
const at::Tensor& input,
double output_scale,
int64_t output_zero_point) = 0;
virtual at::Tensor apply_relu(
const at::Tensor& input,
double output_scale,
int64_t output_zero_point) = 0;
virtual at::Tensor apply_dynamic(
const at::Tensor& input,
bool reduce_range) = 0;
virtual std::tuple<at::Tensor, c10::optional<at::Tensor>> unpack() = 0;
virtual torch::List<int64_t> stride() const = 0;
virtual torch::List<int64_t> padding() const = 0;
virtual torch::List<int64_t> output_padding() const = 0;
virtual torch::List<int64_t> dilation() const = 0;
virtual int64_t groups() const = 0;
virtual bool transpose() const = 0;
};
It appears to be a template specification but kSpatialDim
is never used. I was wondering what is the purpose of this kind of design?
Upvotes: 2
Views: 97
Reputation: 4679
I am not sure about this particular example you've given, but one usage I could think of is simply overloading some function based on the template argument, like in this tiny example:
#include <iostream>
template <int dimension = 1>
struct Space {};
template <int d>
void what(const Space<d>&) {
std::cout << "Some space with dimension " << d << ".\n";
}
void what(const Space<1>&) { std::cout << "A line.\n"; }
void what(const Space<2>&) { std::cout << "A plane.\n"; }
void what(const Space<3>&) { std::cout << "A three-dimensional space.\n"; }
int main() {
Space<> one_d;
Space<2> two_d;
Space<3> three_d;
Space<4> four_d;
what(one_d);
what(two_d);
what(three_d);
what(four_d);
}
This will print:
A line.
A plane.
A three-dimensional space.
Some space with dimension 4.
See also here.
This works because basically every template instantiation constitutes a new type, as if you've had declared separate types for every (necessary) dimension. So this will allow users to implement different behavior depending on the dimension that the class is instantiated with.
Upvotes: 1