1

I have the following reduced example where I try to map from an enumeration that I created (f32) to a native-type (float). I am trying to extend based on this answer.

#include <any>
#include <iostream>

enum class Scalar {
    f32,
    i32
};

template <enum Scalar> struct DeduceNative;

template <>  struct DeduceNative<Scalar::f32> {
    using type = float;
};

template <>  struct DeduceNative<Scalar::i32> {
    using type = int;
};


void example(){
    DeduceNative<Scalar::i32>::type izero(0);
    DeduceNative<Scalar::f32>::type fzero(0);
    
    std::cout << izero << " ";
    std::cout << fzero << "\n";
}

#if 1
template <enum Scalar>
struct Zero {
    DeduceNative<Scalar>::type value() { return 0; }
};

void working_draft(){
    Zero<Scalar::f32> fzero;
    Zero<Scalar::f32> izero;
    std::cout << fzero.value() << " " <<  izero.value() << std::endl;
}
#endif

int main(){
    example();
    return 0;
}

The working_draft fails to compile (with the error below) while the example is working as intended. Why is the type not being deduced properly in working_draft case?

<source>:24:24: error: type/value mismatch at argument 1 in template parameter list for 'template<Scalar <anonymous> > struct DeduceNative'
   24 |     DeduceNative<Scalar>::type value() { return 0; }
jerin
  • 91
  • 1
  • 6

2 Answers2

4

You want this

template <Scalar sc>
struct Zero {
    typename DeduceNative<sc>::type value() { return 0; }
};

Zero has a non-type template argument. enum Scalar is one but it is unnamed. Then you tried DeduceNative<Scalar> which makes no sense. Scalar is not the name of the template argument, but of the enum type. You also need typename keyword because its a dependant name.

PS: Nothing is being deduced in your code. Deduction is when the arguments are not explicitly given but infered from eg function arguments.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
2

You've got the template syntax wrong. Your template has a non-type (integral) parameter, for which you don't need introductory keywords such as enum (the possibility to use one is a remainder from C syntax), but you need to give it a name, e. g., s to refer to that parameter in the template body.

template <Scalar s>
struct Zero
{
    typename DeduceNative<s>::type value() { return 0; }
};
ach
  • 2,314
  • 1
  • 13
  • 23