Skip to main content
improved sample code
Source Link
greatwolf
  • 1.9k
  • 2
  • 19
  • 23

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, Ttypename RefTrait<T>::Ref currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >interpolateImp<T>(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a valueType to your RefTraits policy. You would then use typename T::valueType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.

Edit: After thinking about my above code some more, I noticed it could be simplified a bit by just keeping the syntax the same as the OP. I've updated mines to reflect that.

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, T currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a valueType to your RefTraits policy. You would then use typename T::valueType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, typename RefTrait<T>::Ref currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp<T>(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a valueType to your RefTraits policy. You would then use typename T::valueType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.

Edit: After thinking about my above code some more, I noticed it could be simplified a bit by just keeping the syntax the same as the OP. I've updated mines to reflect that.

gave more appropriate type name
Source Link
greatwolf
  • 1.9k
  • 2
  • 19
  • 23

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, T currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a nonRefTypevalueType to your RefTraits policy. You would then use typename T::nonRefTypevalueType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, T currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a nonRefType to your RefTraits policy. You would then use typename T::nonRefType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, T currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a valueType to your RefTraits policy. You would then use typename T::valueType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.
Source Link
greatwolf
  • 1.9k
  • 2
  • 19
  • 23

If I understand your question correctly, using the RefTrait policy in your second solution is acceptable but you want to avoid specifying template parameters from the client code that's using it.

If so then perhaps one possible idea is to create an inline wrapper function around your interpolate for marshaling the call so type deduction happens automatically:

template <>
struct RefTrait<Vector> { typedef const Vector &Ref; };

template <typename T>
T interpolateImp(Buffer& buffer, T currentValue, const float prop)
{
    T bufferValue;
    buffer.readT(&bufferValue);
    return currentValue + (bufferValue-currentValue)*prop;
}

template <typename T>
inline T interpolate(Buffer& buffer, T &currentValue, const float prop)
{
    return interpolateImp< typename RefTrait<T>::Ref >(buffer, currentValue, prop);
}

It doesn't avoid the overloading but it'll at least help with the automatic type-deduction when you try to use it:

floatVal  = interpolate(buffer, floatVal, 0.5f);
vectorVal = interpolate(buffer, vectorVal, 0.5f);

And the interpolate wrapper should get optimized away into just a interpolateImp call when the compiler inlines it.

But I would recommend taking a look at what Mike said first and find out really how much of a performance impact this is. If afterwards you still decide to pursue this route there are two things to keep in mind.

  • Caveat with using your current RefTrait. At the moment, T bufferValue; in your interpolate creates a locate T variable but doesn't initialize it. This poses a problem if T = const Vector&. Furthermore, it also means you're unable to change this T object later on should you need to. One possible way to fix it is to also add a nonRefType to your RefTraits policy. You would then use typename T::nonRefType to create any locates you would need inside interpolate.
  • Using templates in this matter will reduce code clarity unless you're extra dilgent. The syntax has a matter of exploding in your face and could be difficult to get right especially if you're trying to cover the funny corner cases. Be sure to weight the tradeoffs.