Is it possible to have a C++ template function which can access different fields in its input data depending on what type of input data was passed to it?
e.g. I have code of the form:
typedef struct
{
int a;
int b;
}s1;
typedef struct
{
int a;
}s2;
template <class VTI_type> void myfunc(VTI_type VRI_data, bool contains_b)
{
printf("%d", VRI_data.a);
if(contains_b) // or suggest your own test here
printf("%d", VRI_data.b); // this line won't compile if VTI_type is s2, even though s2.b is never accessed
}
void main()
{
s1 data1;
data1.a = 1;
data1.b = 2;
myfunc <s1> (data1, true);
s2 data2;
data2.a = 1;
myfunc <s2> (data2, false);
}
So we want to use field A from many different data types, and that works fine.
However, some data also has a field B that needs to be used - but the code which accesses field B needs to be removed if the template knows it's looking at a data type that doesn't contain a field B.
(in my example, the structures are part of an external API, so can't change)
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.
Explanation: As a template feature allows you to write generic programs. therefore a template function works with any type of data whereas normal function works with the specific types mentioned while writing a program.
A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.
To elaborate the suggested use of template specialization:
template <class T> void myfunc(T data)
{
printf("%d", VRI_data.a);
}
// specialization for MyClassWithB:
template <>
void myfunc<MyClassWithB>(MyClassWithB data)
{
printf("%d", data.a);
printf("%d", data.b);
}
However, that requires a specialization per-class, there is no "auto-detection" of b. Also, you repeat a lot of code.
You could factor out that "having b" aspect into a helper template. A simple demonstration:
// helper template - "normal" classes don't have a b
template <typename T>
int * GetB(T data) { return NULL; }
// specialization - MyClassWithB does have a b:
template<>
int * GetB<MyClassWithB>(MyClassWithB data) { return &data.b; }
// generic print template
template <class T> void myfunc(T data)
{
printf("%d", VRI_data.a);
int * pb = GetB(data);
if (pb)
printf("%d", *pb);
}
Solution 1: You could use template specialization. The specialization might be performed on per-class basis, or on some more general trait.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With