Home > Net >  Is it possible to use a literal double if a given template type doesn't have a method that retu
Is it possible to use a literal double if a given template type doesn't have a method that retu

Time:07-12

Here's my problem, I have a class Foo() which holds two doubles, its value and an extra one:

class Foo {
    public:
    Foo(double value, double extra) :
        value_(value), extra_(extra) {

        }

    operator double() const
    {
        return value_;
    }

    double extra() const {
        return extra_;
    }

private:
    double value_;
    double extra_;
};

I want to be able to access the value_ as if it was a literal double, hence the double() operator, but I also want to access its extra value.

Now say I have a template class that holds a Foo and a literal double, and can access the value and extra value of both (extra value of literal doubles should always be 1):

template <typename T1, typename T2>
class Testing {

public:
    Testing(T1 a, T2 b) :
        a_(a), b_(b) {


    }

    void test() {
        double valA =  a_;
        double valB = b_

        std::cout << valA << " " << valB << std::endl;

        double extraA = a_->extra();
        double extraB = b_->extra();
        std::cout << extraA << " " << extraB << std::endl;
    }

private:
    T1 a_;
    T2 b_;

};

This obviously doesn't compile, because double doesn't have any extra() method.

Would there be any way to implement this and say something (in compile time) like, if either type T1 or T2 doesn't have an extra() method, simply use 1 when calling extra?

The only thing I've come up with that works are these operators for Foo (which I wouldn't use either way):

double operator*(const double& rhs) const
{
    return extra() - 1;
}

double operator/(const double& rhs) const
{
    return value_;
}

(I had to use the division operator instead of double() to avoid ambiguity)

Combined with this:

void test() {
    double valA =  a_/1;
    double valB = b_/1;

    std::cout << valA << " " << valB << std::endl;
    double extraA = a_*0   1;
    double extraB = b_*0   1;
    std::cout << extraA << " " << extraB << std::endl;
}

But I don't think this is very elegant. A more "readable" option could be to have a wrapper class around double that has the extra() method, but considering I would be working with many of these values I don't like the memory overhead. EDIT: This wouldn't work, I need the double to be literal.

Thanks for the help, I would also be intereted in knowing whether there are would be any performance issues with the aforementioned possible solution.

CodePudding user response:

To me it sounds like you could do several things. Either Testing should not be a template and only have Foo members, so that you can use a converting constructor for Foo,

Foo(double value, double extra = 1);

to allow implicit conversion from a single double. Or, as you say, another Foo-like class whose extra() simply returns 1.

Otherwise, you could obtain the extra value using functions like these:

template<typename T>
double extra(T const&) { return 1; }

double extra(Foo const& foo) { return foo.extra(); }
  • Related