【问题标题】:template parameter inference for std pair [duplicate]标准对的模板参数推断
【发布时间】:2022-01-15 08:03:51
【问题描述】:

在下面的代码中,X x1{{100,5.55}, "abc"} 编译失败(“候选模板被忽略:无法推断模板参数 'T1'”)。 我认为这是因为模板推导不考虑隐式转换,因此编译器不会将第一个参数视为 std::pair。

有什么方法可以使X x1{{100,5.55}, "abc"} 语法起作用吗?我想避免在参数中显式使用 std::pair,因为我正在重构一个大型代码库,该表达式在许多地方都使用。
(在当前代码中,构造函数没有模板化,因为它使用 std::variant 创建了一个综合类,该类使用 int、double、std::string 等的隐式构造函数来处理多种类型。我正在尝试替换这个类使用保留底层数据类型的模板化构造函数,以提高类型安全性。)

#include <utility>

struct X
{
template <class T1, class T2> X(std::pair<T1,T2>, const char*){}
};

int main()
{  
  X x{std::pair{100,5.55}, "abc"};  // OK
//  X x1{{100,5.55}, "abc"};        // Compile error
}

【问题讨论】:

  • 我的猜测是{100, 5.55}被推导出为std::initializer_list,而std::pair一定没有对应的构造函数。
  • @Mansoor 我认为它根本没有被推断出来。据我所知,这是non-deduced context
  • @Mansoor 你错了。 OP已经提到了代码不起作用的正确原因,即模板参数推导中不考虑隐式转换
  • 添加X(std::pair&lt;int,double&gt;, const char*){}重载:)
  • @rustyx 这导致{5.5, 1} 对通过std::pair&lt;int, double&gt; 构造函数。 IMO 非常容易出错。

标签: c++ templates


【解决方案1】:

我没有完美的解决方案,但如果我足够了解您的约束,那么如果新代码需要显式使用 std::pair{} 并没有什么大不了的,但旧代码必须保持兼容。

引入一个简单的兼容性struct 和(ab)使用聚合初始化来提供构造函数重载怎么样?

#include <utility>
#include <iostream>

struct X
{
    template <class T1, class T2> X(std::pair<T1,T2>, const char*)
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    struct LegacyPair
    {
        int a;
        double b;
    };

    X(LegacyPair p, const char* text) :
        X(std::pair{p.a, p.b}, text)
    {}
};

int main()
{
    X x1{std::pair{100,5.55}, "abc"};
    X x2{{100,5.55}, "abc"};
    //X x3{{3.14,5}, "abc"}; // error
    X x4{std::pair{3.14,5}, "abc"};
}

这个输出:

  • X::X(std::pair&lt;_T1, _T2&gt;, const char*) [with T1 = int; T2 = double]x1
  • X::X(std::pair&lt;_T1, _T2&gt;, const char*) [with T1 = int; T2 = double]x2
  • x3 的错误(比意外构造 std::pair&lt;int, double&gt; 好)。因为{}在这里是聚合初始化,所以不允许隐式转换,所以这个重载被丢弃了。哪个好!
  • X::X(std::pair&lt;_T1, _T2&gt;, const char*) [with T1 = double; T2 = int]x4

【讨论】:

  • 最初的用途是通过 std::variant 将多种类型包装到一个类中(带有用于整数、双精度、字符串等的隐式构造函数)。我已经编辑了问题以澄清这一点。
猜你喜欢
  • 1970-01-01
  • 2022-12-02
  • 1970-01-01
  • 2023-03-31
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
相关资源
最近更新 更多