StefTheDrummer
StefTheDrummer

Reputation: 139

C++ Template Template Type Inference

So i have a struct something like this:

template<uint8 N>
class SomeStruct { ... };

class Node {
    SomeStruct<0> a;
    SomeStruct<2> b;
    SomeStruct<4> c;
};

and I have a template function, that does something on a specific field of Node:

template<uint8 N>
using NodeFieldPtr = SomeStruct<N> Node::*;

template <uint8 N, NodeFieldPtr<N> F>
void doSomething(Node* node0, Node* node1) { ... }

I find it annoying to have to specify "N" on doSomething() again, because calling it is not elegant:

doSomething<2, &Node::b>(...);

How can I tell the compiler "nicely" not to care about the exact template arguments of SomeStruct<>. Something like a wildcard.

template <NodeFieldPtr<?> F> //<- unfortunately not C++
void doSomething(Node* node0, Node* node1) { ... }

doSomething<&Node::b>(...);

Upvotes: 1

Views: 225

Answers (3)

To complement the other answers, if you wish to constrain the type of F and have the syntax you are after, you may employ a custom type trait:

template<int N>
using NodeFieldPtr = SomeStruct<N> Node::*;

template<typename> struct is_some_struct_memptr                  : std::false_type{};
template<int N>    struct is_some_struct_memptr<NodeFieldPtr<N>> : std::true_type {};

With that in hand, we can constrain doSomething in C++17:

template <auto F>
auto doSomething(Node*, Node*) -> std::enable_if_t<is_some_struct_memptr<decltype(F)>::value>
{
}

Or even C++20:

template <auto F>
void doSomething(Node*, Node*) requires (is_some_struct_memptr<decltype(F)>::value)
{
}

Upvotes: 2

Jarod42
Jarod42

Reputation: 217075

How about auto (since C++17):

template <auto F>
void doSomething(Node* node0, Node* node1)
{
// ... 
}

Upvotes: 3

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

You can use an auto non-type template parameter since C++17:

template <auto F>
void doSomething() { }

int main()
{
    doSomething<&Node::b>();
}

live example on godbolt.org

Upvotes: 3

Related Questions