Search code examples
c++templatesaliasquadruple-precision

Ignore 'long' specifier for custom type in c++


I have a type and a template class

#ifdef USE_QUAD
using hybrid = __float128;
#else
using hybrid = double;
#endif

template<typename T>
struct Time {
    int day;
    long T dayFraction; // This is an example, I need both in here, T and long T;
};

And to make things complicated: A nesting class

template<typename T>
struct State {
    Time<T> time;
    std::vector<T> position;
}

Now I want to use the class in my code as hybrid and double simultaneously, like

State<hybrid> stateH; // sometimes precision needed
State<double> stateD; // precision never needed

and let the preprocessor take care of what hybrid is supposed to be.

The code, however, perfectly compiles if hybrid = double, but not so much, if hybrid = __float128, because of the long T dayFraction; in the Time class.

Is there a workaround to define an alias like

using long __float128 = float128;

?

I had a workaround with defining a longHybrid like:

#ifdef USE_QUAD
using hybrid     = __float128;
using longHybrid = __float128;
#else
using hybrid     = double;
using longHybrid = long double;
#endif

But forwarding two template parameters would affect a bit of code and feels kind of redundant. I would love to hear any ideas.


Solution

  • You can't actually write long T and expect that to be interpreted as long double when T is double. If it works for you, that's a non-portable quirk of your compiler.

    If you want "regular" and "long" versions of a type, different for double but the same for float128, one way to do it would be to define a template like this:

    template <typename T> struct Longer {
        using type = T;
    };
    template <> struct Longer<double> {
        using type = long double;
    };
    

    Instead of long T in struct Time, use typename Longer<T>::type.