0

I have a template function and a partial specialized version of it like this:

template<typename _T>
int values_in_range(const _T &beg, const _T &end) {
    throw std::runtime_error("unsupoorted data type");
}

template<>
int values_in_range<int>(const int &beg, const int &end) {
    return end - beg;
}

These code works good and then I want to extend the capabilities of the function to a template class that have two template parameters like this:

template<typename _Ty, size_t _Dims>
class vec {
    // ...
};

How to partial specialize the function values_in_range for class vec with keeping the parameter _Dims unspecialized?

I try following code but encount error:

template<size_t _Dims>
int values_in_range<vec<int, _Dims>>(const vec<int, _Dims> &beg,
        const vec<int, _Dims> &end) { // <-- compiling error
    int ret = 0;
    for (int i = 0; i < _Dims; ++i) {
        //some computing here
    }
    return ret;
}

The error message:

error: non-class, non-variable partial specialization ‘values_in_range<vec<int, _Dims> >’ is not allowed
[build]   349 | int values_in_range<vec<int, _Dims>>(const vec<int, _Dims> &beg,
[build]       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Devymex
  • 446
  • 3
  • 17
  • There ain't no such thing as a partial specialization of a function template. But unlike classes, functions can be overloaded. Just make it `template int values_in_range(const vec &beg, const vec &end) {...}` – Igor Tandetnik Jan 26 '23 at 14:57
  • there is no partial specialization for function templates. (in your first example you are using the term wrong. It not *partial* specialization) – 463035818_is_not_an_ai Jan 26 '23 at 14:58
  • Partial specialization of a function is forbidden. You need move implementation into a class to resolve this problem. – Marek R Jan 26 '23 at 14:58
  • As an aside, note that identifiers beginning with an underscore followed by a capital letter, like `_Dims`, are reserved for the implementation. Your code exhibits undefined behavior by way of using such reserved names. – Igor Tandetnik Jan 26 '23 at 14:59
  • fwiw, when I want to answer this quesiton, I have to turn your code into a [mcve] to see the error, to make sure my fix really fixes it, and to test my solution. This is soo much simpler of you post a [mcve]. I suppose its not much more needed that not to remove the includes – 463035818_is_not_an_ai Jan 26 '23 at 15:03
  • if you just want some special case, a simple way is use `if constexpr` – apple apple Jan 26 '23 at 18:08
  • or a wrapper function that forward it's argument to real implementation would work as well. – apple apple Jan 26 '23 at 18:09
  • of course, only if you really cannot use overload directly – apple apple Jan 26 '23 at 18:11

1 Answers1

0

There is no partial specialization of function templates. Your first snippet of code is no partial specialization. You can partially specialize class templates. A function template can usually be refactored to a class template with operator().

template<typename _T>
struct values_in_range {
    int operator()(const _T &beg, const _T &end) const {
        throw 42;
    }
};

template<>
struct values_in_range<int> {
    int operator()(const int &beg, const int &end) const {
        return end - beg;
    }
};


template<typename _Ty, unsigned _Dims>
class vec {};

template<unsigned _Dims>
struct values_in_range<vec<int,_Dims>> {
    int operator()(const vec<int, _Dims> &beg, const vec<int, _Dims> &end) const {
        int ret = 0;
        for (int i = 0; i < _Dims; ++i) {
            //some computing here
        }
        return ret;
    }
};
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185