Reputation: 139
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
Reputation: 170045
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
Reputation: 217075
How about auto
(since C++17):
template <auto F>
void doSomething(Node* node0, Node* node1)
{
// ...
}
Upvotes: 3
Reputation: 93264
You can use an auto
non-type template parameter since C++17:
template <auto F>
void doSomething() { }
int main()
{
doSomething<&Node::b>();
}
Upvotes: 3