【问题标题】:C++ Template Template Type InferenceC++ 模板模板类型推断
【发布时间】:2021-03-25 10:08:33
【问题描述】:

所以我有一个类似这样的结构:

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

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

我有一个模板函数,它在节点的特定字段上做一些事情:

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

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

我觉得不得不再次在doSomething() 上指定“N”很烦人,因为调用它并不优雅:

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

我怎样才能“很好地”告诉编译器不要关心SomeStruct&lt;&gt; 的确切模板参数。类似于通配符

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

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

【问题讨论】:

  • 迄今为止最轻松的建议:“C++17 模板 ”。但没有很好地描述函数的签名。

标签: c++ templates inference


【解决方案1】:

自 C++17 起,您可以使用 auto 非类型模板参数:

template <auto F>
void doSomething() { }

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

live example on godbolt.org

【讨论】:

  • 是的......但不够“约束”
【解决方案2】:

auto(C++17 起)怎么样:

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

【讨论】:

  • 是的...但不够“约束”
  • 您可以在 C++20 中创建一个概念,或者在 C++17 中使用具有适当特征的 SFINAE/static_assert。
  • @StefTheDrummer 它受制于您使用指针在实现中的某处调用Node 的成员这一事实。您可以通过提供更好的错误消息来改进它,但约束已经存在(如果没有,为什么要人为地引入它?)
【解决方案3】:

为了补充其他答案,如果您希望限制 F 的类型并且具有您所追求的语法,您可以使用自定义类型特征:

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 {};

有了这个,我们可以在 C++17 中约束 doSomething

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

甚至是 C++20:

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

【讨论】:

  • 风格问题,但我不喜欢你的命名。 is_some_struct_memptr 似乎暗示它检查是否被 mempr 到“一些”结构(读作“任何结构”),但它只是关于 SomeStruct
  • @largest_prime_is_463035818 - 如果有人完全忽略了我使用 OP 自己的名字这一事实,那当然。
  • 我并没有忽视这一点,相反,这只是我的观点。 OPs 结构被称为SomeStruct 而不是some_struct。没关系,很清楚上下文是什么意思
  • @largest_prime_is_463035818 - 当转换成蛇形盒时,它肯定被称为some_struct。谈论在非问题上浪费击键。
  • @StefTheDrummer - 花了大约十年的元编程。它将变得足够可读。你不能一边吃蛋糕一边吃。你想要一个语法很好的约束参数吗?约束必须由阐明和应用。
猜你喜欢
  • 2023-03-31
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2020-07-09
相关资源
最近更新 更多