3

我正在尝试在“垂直()”函数中使用模板参数推导:

#include <iostream>

template <typename component = double>
struct offset {
  component x;
  component y;
};

template <typename component>
offset(component x, component y) -> offset<component>;

template <typename component>
offset<component> perpendicular(offset<component> const &o) {
  return offset{o.y, -o.x};
}

template <typename component>
std::ostream &operator<<(std::ostream &s, offset<component> const &o) {
  return s << '(' << o.x << ", " << o.y << ')';
}

int main() {
  std::cout << perpendicular({3.1, 1.2}) << '\n';
  return 0;
}

然而,这不会编译;铿锵声(带-std='c++17')说:candidate template ignored: couldn't infer template argument 'component' offset<component> perpendicular(offset<component> const &o) {

我应该辞职写作perpendicular(offset{1.0, 2.0})还是有办法给编译器一个提示?

4

3 回答 3

3

问题{/*..*/}在于它没有类型,并且大多数情况下只能推断为std::initializer_list<T>or T[N]

因此,以下将允许所需的语法:

template <typename component>
offset<component> perpendicular(component const (&o)[2]) {
    return offset{o[1], -o[0]};
    // return perpendicular(offset{o[0], o[1]});
}

演示

于 2019-09-26T14:48:34.587 回答
0

Jarod42 的答案为您提供了您想要的语法,但我主观上认为这并不理想。您最初想传递一个偏移量,但现在您要传递一个数组并将其转换为偏移量。这是一种奇怪的类型关系。

而不是结构和单独的函数,只需将其全部放入 Offset 类中。这实际上并没有任何额外的工作,并且使 C++ 变得更好。你所拥有的更类似于面向对象的 C。

#include <iostream>

// Create a self-contained class
template <typename Component = double>
class Offset {
 public:
  Offset(Component x, Component y) : x(x), y(y) {}

  // No longer requires function parameters
  Offset const perpendicular() const { return Offset(y, -x); }

  // I appreciate your use of east const
  friend std::ostream& operator<<(std::ostream& sout,
                                  Offset<Component> const& o) {
    return sout << '(' << o.x << ", " << o.y << ')';
  }

 private:
  Component x;
  Component y;
};

int main() {
  // Subjectively much cleaner to read and understand
  std::cout << Offset{3.1, 1.2}.perpendicular() << '\n';
  return 0;
}

为了将来参考,可以decltype(auto)用作您的返回类型,并从 C++14 开始完全放弃尾随返回类型语法。

于 2019-09-26T15:15:09.110 回答
0

一种选择是添加一个perpendicular需要两个值的重载。

template <typename component>
offset<component> perpendicular(component v1, component v2) {
    return {v2, -v1};
}

这也可以通过参数包变得更通用,可能与std::common_type.

于 2019-09-26T15:15:43.193 回答