简体   繁体   中英

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.)

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.

You cannot use:

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;
};

when the expected types for FP is float or double since a non-type template parameter cannot be a float or a double .

You can use what you came up with as your solution:

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) {}
};

It's not clear how K is going to be used but you can also use:

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

and create instances of the class as:

SimRank<double, 5> sd(0.8, 0.0);
SimRank<float, 10> sf(0.8f, 0.0f);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM