`std :: make_tuple`的原因是什么?

Joj*_*GME 24 c++ c++11 stdtuple

我的意思是为什么std::make_tuple存在?我知道在某些情况下,该函数会减少您必须键入的字符数,因为您可以避免使用模板参数.但这是唯一的原因吗?std::tuple当其他类模板没有这样的功能时,该功能存在的特殊之处是什么?是否只是因为你可能std::tuple在这种情况下更频繁地使用?


以下是两个std::make_tuple减少字符数量的示例:

// Avoiding template parameters in definition of variable.
// Consider that template parameters can be very long sometimes.
std::tuple<int, double> t(0, 0.0); // without std::make_tuple
auto t = std::make_tuple(0, 0.0);  // with std::make_tuple

// Avoiding template parameters at construction.
f(std::tuple<int, double>(0, 0.0)); // without std::make_tuple
f(std::make_tuple(0, 0.0));         // with std::make_tuple
Run Code Online (Sandbox Code Playgroud)

但是,如上所述,对于许多其他类模板,您没有这样的函数.

luk*_*k32 27

因为你不能对构造函数使用参数推导.你需要明确写 std::tuple<int, double>(i,d);.

它使得创建元组并将其一次性传递给另一个函数变得更加方便.

takes_tuple(make_tuple(i,d))VS takes_tuple(tuple<int,double>(i,d)).

当类型id更改时,更少的地方可以更改,特别是如果旧类型和新类型之间可能存在转换.

如果有可能写std::tuple(i,d);,make_*将(可能)是多余的.

(不要在这里问为什么.也许出于类似的原因,为什么语法A a();不会调用默认的构造函数.有一些痛苦的c ++语法特性.)

更新说明: 正如Daniel正确地注意到的那样,c ++ 17将得到增强,因此模板参数推导将适用于构造函数,并且这种委托将变得过时.

  • 从**C++ 17**开始,可以使用**类模板推导**,即编写`std :: tuple t(1,1.0,'a');`或`auto t = std :: tuple(1,1.0,'a');`.有关详细信息,请参见[此处](http://en.cppreference.com/w/cpp/language/class_template_deduction). (7认同)
  • @luk32“这样的委托将变得过时”我不同意:如果你在`std::ref()`调用中包装一些东西,`std::make_tuple`将使用`X&amp;`,这在C++17中仍然有用,因为[`std::tuple`的推导指南](http://en.cppreference.com/w/cpp/utility/tuple/deduction_guides)似乎不能处理这种情况。 (5认同)

Sha*_*our 9

我们可以找到我们需要的原因make_tuple以及提案N3602中的各种其他make_*实用程序:构造函数的模板参数推导(表示强调我的):

本文提出将函数的模板参数推导扩展到模板类的构造函数.描述问题和解决方案的最清晰方式是一些例子.

假设我们已经定义了以下内容.

vector<int> vi1 = { 0, 1, 1, 2, 3, 5, 8 }; 
vector<int> vi2; template<class Func> 
    class Foo() { 
        public: Foo(Func f) : func(f) {} 
        void operator()(int i) { os << "Calling with " << i << endl; f(i); } 
        private: 
        Func func;
    };
Run Code Online (Sandbox Code Playgroud)

目前,如果我们想要实例化模板类,我们需要指定模板参数或使用"make_*"包装器,利用函数的模板参数推导,或者完全解决:

pair<int, double> p(2, 4.5); 
auto t = make_tuple(4, 3, 2.5); 
copy_n(vi1, 3, back_inserter(vi2)); // Virtually impossible to pass a lambda to a template class' constructor
for_each(vi.begin(), vi.end(), Foo<???>([&](int i) { ...}));
Run Code Online (Sandbox Code Playgroud)

请注意,该提案正在通过EWG第60期进行跟踪.