繁体   English   中英

C ++模板class = typename

[英]C++ template class = typename

什么template <class = typename T::type>是什么意思? 你能引用我的博客,说明这个吗?

这个问题最初来自对cpp引用sfinae的解释

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);

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

struct foo {
    using bar = int;
};

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

    // var has type int
}

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

好的,现在这个class =意味着什么?

class =表示与typename =相同的东西。 在声明模板类型参数时,我们使用classtypename引入:

template<typename A, typename B>
struct baz {};

但是作为C ++中的任何参数,名称是可选的。 我本来可以写这个,以下是完全等价的:

template<typename, typename>
struct baz {};

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

void func(int a, int b = 42);

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

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

void func(int, int = 42);

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

template<typename, typename = float>
struct baz {};

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

把它们放在一起

现在我们有这个声明:

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的成员类型。 我们通过指定typename明确告诉编译器T::type必须是T的成员类型。 第三个参数类似于第二个参数。

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

这与简单重载非常相似。 你有f功能。 它需要一个float参数,另一个带有std::string重载。 想象一下你叫f(9.4f) 编译器是否因为一个float不能构造std::string而窒息? 没有! 编译器不是傻瓜。 它将尝试另一个重载,并将找到float版本并调用它。 在SFINAE中,可以进行类似的类比。 编译器不会停止,因为某些重载需要模板参数中的未定义类型。 它会尝试另一个重载。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM