Search code examples
c++templatesc++11typename

Can one parameter in a C++11 template depend on another?


My class SimRank has two floating-point constant parameters, C and D. I would like them to be static constexprs, not const instance members. But I also want to let the user choose which kind of floating-point to use, float for size or double for precision.

The obvious way to do it is like this:

template<typename FP, int _K, FP _C, FP _D>
class SimRank {
    static constexpr int K = _K;
    static constexpr FP C = _C;
    static constexpr FP D = _D;
};

template<int _K, float _C, float _D>
class SimRank<float> {};

template<int _K, double _C, double _D>
class SimRank<double> {};

int main() {
    SimRank<5, 0.8, 0> sd; // uses double
    SimRank<10, 0.6f, 0.05f> sf; // uses float
    return 0;
}

But gcc prints many error messages when I try this, so apparently that syntax doesn't exist. I also can't do anything like this:

template<typename FP> template<int _K, FP _C, FP _D> class SimRank {...};

Is there any syntax that lets me specify K, C, D, and the type of C and D at compile time? Right now I've settled for const members:

template<typename FP>
class SimRank {
private:
    const int K;
    const FP C;
    const FP D;
public:
    SimRank(int K, FP C, FP D) : K(K), C(C), D(D) {}
};

class SimRankF : public SimRank<float> {
public:
    SimRankF(int K, float C, float D) : SimRank<float>(K, C, D) {}
};

class SimRankD : public SimRank<double> {
public:
    SimRankD(int K, double C, double D) : SimRank<double>(K, C, D) {}
};

int main() {
    SimRankD sd(5, 0.8, 0.0);
    SimRankF sf(10, 0.6f, 0.05f);
    return 0;
}

(Actually, even if I have to keep the const member solution, I would like a way to define SimRankF and SimRankD without repeating the constructor for each. Leaving it out makes gcc print error: no matching function for call to 'SimRankF::SimRankF(int, float, float)' when I try to instantiate a SimRankF.)


Solution

  • There are two problems,

    First, template non-type parameters cannot be of type float or double.

    Second, the syntax of partial specialization declaration (and its use in main) is wrong.

    It has nothing to do with C++11, BTW.

    Read an introductory text on C++ templates is the best way to go for you.