【问题标题】:what is difference of two kinds of template examples? [duplicate]两种模板示例有什么区别? [复制]
【发布时间】:2020-05-12 22:58:45
【问题描述】:

我打算让“MyVector”类具有 3D 坐标(X、Y、Z)。

我尝试使构造函数具有三种类型的函数参数,每种参数类型都满足 std::is_arithmetic。

我做了两个不同的代码。一个运行良好,但另一个不工作。

这是我的代码。

main.cpp

#include <iostream>
#include "MyVector.h"

using namespace std;

int main()
{
    MyVector mv1 = MyVector();
    int x = 5;
    double y = 2.0;
    float z = 5.0;
    MyVector mv2 = MyVector(z, y, x);
    //MyVector mv3 = MyVector(&x);


    cout << boolalpha << is_arithmetic<int>::value << endl;
    cout << mv2;

}

MyVector.h

#pragma once

#include <type_traits>
#include <iostream>

class MyVector
{

public:
    MyVector();
    MyVector(const MyVector&);


    //This is What I wanted
    template <typename N1, typename = std::enable_if_t<std::is_arithmetic<N1>::value >
            , typename N2, typename = std::enable_if_t<std::is_arithmetic<N2>::value >
            , typename N3, typename = std::enable_if_t<std::is_arithmetic<N3>::value > >
    MyVector(const N1& x, const N2& y, const N3& z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    //Working
    template <typename N, typename = std::enable_if_t<std::is_arithmetic<N>::value >>
    MyVector(const N& x)
    {
        X = 0;
        Y = 0;
        Z = 0;
    }

    //Not Working
    template <typename N, std::enable_if_t<std::is_arithmetic<N>::value >>
    MyVector(const N& x)
    {
        X = 0;
        Y = 0;
        Z = 0;
    }


private:
    float X;
    float Y;
    float Z;

public:
    friend std::ostream& operator<<(std::ostream&, const MyVector&);

};

我不知道下面两个代码有什么区别

1. template <typename N, typename = std::enable_if_t<std::is_arithmetic<N>::value >>
2. template <typename N, std::enable_if_t<std::is_arithmetic<N>::value >>

【问题讨论】:

  • 我首先尝试了第二个版本,参考link。第二个版本给出了这样的错误“没有构造函数“MyVector::MyVector”的实例与参数列表匹配。
  • 这个question 可能对你有帮助。
  • 谢谢你们!我阅读了您链接的内容,这对我有帮助。

标签: c++ templates enable-if typename


【解决方案1】:

这两行代码的操作方式略有不同:

template <typename N, typename = std::enable_if_t<std::is_arithmetic<N>::value
// or with name
template <typename N, typename second = std::enable_if_t<std::is_arithmetic<N>::value

将类型定义为模板(在第一种情况下未命名)并提供默认值(std::enable_if...)。在您的情况下,这归结为&lt;N=int, second=int&gt;This post 有助于了解在哪里使用模板/类型名。而

2. template <typename N, std::enable_if_t<std::is_arithmetic<N>::value >>

有一个非类型模板参数。这归结为&lt;N=int, enable_if&lt;...&gt;::type second=?&gt; 两个版本之间的主要区别以及一个版本“工作”开箱即用的原因是,这一次,这个非类型模板假定的值默认情况下没有指定。您需要指定它或像

这样写
3. template <typename N, std::enable_if_t<std::is_arithmetic<N>::value >* = nullptr>

以下版本是等效的,但提供了一个名称:

4. template <typename N, std::enable_if_t<std::is_arithmetic<N>::value >* second = nullptr>

TLDR

在第二种情况下,您还必须为 enable-if 保护指定默认值,编译器无法推断(或在调用时指定两个模板参数,这是不希望的)。编译器错误提示如果该行(不工作)没有与上面的第(3)行交换:

/home/juli/te.cc:37:5: note: candidate: ‘template<class N, typename std::enable_if<std::is_arithmetic<_Tp>::value, void>::type <anonymous> > MyVector::MyVector(const N&)’
   37 |     MyVector(const N& x)
      |     ^~~~~~~~
/home/juli/te.cc:37:5: note:   template argument deduction/substitution failed:
/home/juli/te.cc:63:30: note:   couldn’t deduce template parameter ‘<anonymous>’
   63 |     MyVector mv3 = MyVector(x);

根据您使用的标准,查看c++2a 的新引入的concepts 功能可能会很有趣。

【讨论】:

  • 这正是我想要的!非常感谢,我读了你链接的东西,它对我也有很大帮助。

    所以我明白
    第一个版本意味着两个类型名的声明,工作正常,因为模板替换成功。

    第二个包括一个类型名,非类型模板价值。非类型模板值的类型为'enable_if',并且它的指针已初始化,所以当我尝试像这样实例化 MyVector 时,
    'MyVector mv = MyVector("ss");'
    由于第二个非类型模板值的类型没有类型,替换失败。
  • 'template ::value >* = nullptr>' 你告诉我的这段代码也很好用。
  • 我很高兴我的回答有帮助!在尝试解决您的评论时,我意识到以下几点:在我的示例中,我有点使用“不一致”的命名:在第一个代码块中,我将名称“第二”分配给我的第二个模板参数。因此,我想澄清一下,该 blob 的两个版本是等效的,第一个版本未命名模板(因为我们在实现中不使用它,仅用于 SFINAE),该 blob 中的第二个版本应用名称 'second '对它。 (我只是为了区分第一个 blob 中的第二行或第二个 blob 中的第二行)在我下面写的内容中
  • 非常感谢您的详细解释。我明白了。
猜你喜欢
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 1970-01-01
  • 2012-09-08
相关资源
最近更新 更多