【问题标题】:Template type deduction according to constructor argument根据构造函数参数推导模板类型
【发布时间】:2018-03-25 08:41:42
【问题描述】:

我有一个类模板,它的构造函数接受一个类型为模板参数的可调用对象。我希望推断出该类型,因此我不必在实例化类时指定它。

不幸的是,类型推导在下面的示例中不起作用。有没有办法让它工作?

template<typename F>
class C {
public:
   C(F&& f) : m_f{f} {}
private:
   F m_f;
};

class D {
public:
    static int s() { return 0; }
private:
   C<decltype(&s)> c {&s}; // OK
   C<> c2 {&s};            // error, not enough template parameters
};

https://wandbox.org/permlink/8cphYR7lCvBA8ro4

请注意,这类似于Can template parameter deduction be used in class data members?,但在这里我要问的是获得与工作类似的东西,而不是标准合规性。

还有一点需要注意的是,虽然在上面的示例中重新指定模板参数的类型只是一个非 DRY 的不便(下面的答案之一建议使用宏来解决),但我不确定它是如何解决的如果该实例是数据成员,则可以拥有C 的实例,其中F 是非全局lambda 函数类型(例如,当场定义的函数类型)。恕我直言,这是一种非常强大和有用的技术。

【问题讨论】:

  • 问题的关键在于这是一个成员变量。会员意味着不扣除。
  • @StoryTeller 另一个问题当然是超级相关的(它甚至提到传递可调用对象作为这个用例)但我不确定它是否重复 - 另一个问题询问这是否是标准行为,而不是是否有某种方法可以使用其他技术进行演绎。
  • C&lt;&gt; 此语法用于默认模板参数,而不是推导。
  • @Yakk Just C 不起作用,auto 不允许用于数据成员。
  • @danra 那你倒霉了;标准不允许这样做,并且编译器可以支持的明显扩展不起作用。

标签: c++ templates c++17 type-deduction


【解决方案1】:

如果您的主要目标是避免输入两次&amp;s,实用的解决方案是定义一个宏:

#define CC(name,value) decltype(C{value}) name{value}

class D {
public:
    static int s() { return 0; }
private:
    CC(c,&s);
    // lambda still not possible:
    // CC(c2,[](){return 42;});
};

【讨论】:

  • 如果你要定义一个宏,这个宏应该是decltype(C{value}) name{value} - 否则你就是在用构造函数重复逻辑,而且你看不出来,因为它隐藏在宏后面。
  • @Barry “使用构造函数复制逻辑”是什么意思?也许分享一个例子来说明为什么编辑后的宏更好?
  • @Danra 宏假定C{x} 推导出为C&lt;decltype(x)&gt;。这不一定会永远正确。
  • @Barry 这很有道理。谢谢!
【解决方案2】:

你可以这样做:

decltype(C{&s}) c{&s};

但我不知道有什么方法可以避免重复 &amp;s

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-21
    • 2019-06-04
    • 2011-07-15
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 2016-06-01
    • 2020-10-17
    相关资源
    最近更新 更多