首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++模板类= typename

C++模板类= typename
EN

Stack Overflow用户
提问于 2018-03-21 13:56:12
回答 1查看 3K关注 0票数 5

template <class = typename T::type>是什么意思?你能给我介绍一下描述这一点的博客吗?

这个问题来源于对cpp参考文献中的sfinae的解释

代码语言:javascript
复制
template <typename A>
struct B { typedef typename A::type type; };

template <
  class T,
  class   = typename T::type,      // SFINAE failure if T has no member type
  class U = typename B<T>::type    // hard error if T has no member type
                                   // (guaranteed to not occur as of C++14)
> void foo (int);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-21 14:32:00

首先,我将解释typename T::type。这只是成员类型的访问。下面是一个访问成员类型的示例:

代码语言:javascript
复制
struct foo {
    using bar = int;
};

int main() {
    foo::bar var{};

    // var has type int
}

那么为什么是typename呢?它只是意味着我们想要访问一个类型。因为我们在一个模板中,而T是一个未知的类型,而foo::bar也可能意味着访问一个静态变量。为了消除歧义,我们表示我们实际上希望通过显式键入typename来访问类型。

好吧,现在class =是什么意思?

class =的含义与typename =的含义相同。在声明模板类型参数时,我们将使用classtypename介绍。

代码语言:javascript
复制
template<typename A, typename B>
struct baz {};

但是,与C++中的任何参数一样,名称是可选的。我本可以写这篇文章,以下内容完全等价:

代码语言:javascript
复制
template<typename, typename>
struct baz {};

另外,您知道在函数参数中,我们可以指定默认值吗?就像这样:

代码语言:javascript
复制
void func(int a, int b = 42);

int main () {
    func(10); // parameter b value is 42
              // We are using default value
}

我们还可以省略参数名称:

代码语言:javascript
复制
void func(int, int = 42);

就像函数参数一样,模板参数可以省略它的名称,并且可以有一个默认值。

代码语言:javascript
复制
template<typename, typename = float>
struct baz {};

baz<int> b; // second parameter is float

把所有的东西都放在一起

现在我们有一项声明:

代码语言:javascript
复制
template <
    class T,
    class   = typename T::type,   // SFINAE failure if T has no member type
    class U = typename B<T>::type // hard error if T has no member type
                                  // (guaranteed to not occur as of C++14)
> void foo (int);

这里,我们声明一个函数,它以int作为参数,并有三个模板参数。

第一个参数是一个简单的命名参数。名称是T,它是一个类型模板参数。第二个参数也是类型参数,但它没有名称。但是,它的默认值是T::type,它是T的成员类型。我们明确地告诉编译器,T::type必须是T的成员类型,方法是指定typename。第三个参数类似于第二个参数。

这就是SFINAE的开场白:当使用默认参数,但T::type作为成员类型不存在时,如何将第二个模板参数分配给它呢?如果T::type不存在,我们就不能分配第二个模板参数。但是编译器不会使它成为一个错误,而是简单地尝试另一个函数,因为有可能会调用另一个函数。

这与简单的重载非常相似。您有f函数。它需要一个float参数,另一个需要std::string的重载。想象一下你打电话给f(9.4f)。编译器会因为std::string不能从float构建而窒息吗?不是的!编译器才不傻。它将尝试另一个重载,并将找到float版本并调用它。在SFINAE中,也可以作类似的类比。编译器不会停止,因为某个地方的重载需要模板参数中未定义的类型。它会尝试另一个过载。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49408294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档