【问题标题】:How to test for typename in class?如何在课堂上测试类型名?
【发布时间】:2019-02-08 09:29:33
【问题描述】:

在类模板Foo 中,我想检查模板参数是否提供名为Bar 的类型。

struct TypeA {using Bar = int;};
struct TypeB {};
template<class T>Foo{};

void main(){
  Foo<TypeA> a; // I want this to compile
  Foo<TypeB> b; // I want this to not compile, but print a nice message.
}

因为我想将它与其他属性结合起来,所以我想要一个hasBar 元函数。所以我可以组合布尔值,然后使用std::enable_if

我试图理解和使用 SFINAE 但失败了:

template<class T, class Enable = void>struct hasBar : std::false_type {};

template<class T>
struct hasBar<T,decltype(std::declval<T::Bar>(),void())> : std::true_type {};

hasBar&lt;TypeA&gt;::value 始终为假。

定义hasBar的正确方法是什么?

或者有没有比using 更好的方法来拥有一个酒吧?

【问题讨论】:

  • 当引用嵌套依赖类型时,您需要直接指定名称是 type 而不是 e.g.静态字段...所以在T::Bar之前使用typename关键字

标签: c++ templates sfinae


【解决方案1】:

最简单的方法是使用依赖类型作为未命名模板参数的默认值。像这样的:

struct with_bar { using Bar = int; };
struct without_bar { };

template <typename T, typename = typename T::Bar>
struct bar_detector { };

int main() {
  bar_detector<with_bar>();
  bar_detector<without_bar>(); // won' compile
}

这会产生一个非常有用的错误消息 (g++ 7.3.0):error: no type named ‘Bar’ in ‘struct without_bar’

【讨论】:

  • 确实如此,但我将不得不添加更多检查,其中大部分是由 typetraits 完成的。
  • @user9400869 如果您想要 bool 或只是编译器错误,则从问题中不清楚,后者更容易实现
【解决方案2】:

您应该在T::Bar 之前添加typename 以指定它是嵌套类型名称,即

template<class T>
struct hasBar<T,decltype(std::declval<typename T::Bar>(),void())> : std::true_type {};

LIVE

顺便说一句:您可以使用std::void_t 使其更简单。例如

template< class, class = std::void_t<> >
struct hasBar : std::false_type { };

template< class T >
struct hasBar<T, std::void_t<typename T::Bar>> : std::true_type { };

【讨论】:

  • 是的,我又忘记了,没有注意到。啊
猜你喜欢
  • 2013-04-01
  • 1970-01-01
  • 2018-01-08
  • 2019-07-03
  • 2015-02-20
  • 2019-03-26
  • 2012-01-12
  • 2015-02-23
相关资源
最近更新 更多