模板化的用法无法选择模板函数用作Visual Studio中的参数

时间:2019-03-07 15:30:17

标签: c++ templates visual-studio-2017 using return-type

这与我制作一个仍然能解决问题的玩具示例一样简单:

struct Vector3f64 {
  double x;
  double y;
  double z;
};

struct Vector3f32 {
  float x;
  float y;
  float z;
};

// I use this to select their element type in functions:
template <typename T>
using param_vector = std::conditional_t<std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, Vector3f64>, double, float>;

// This is the function I want to pull the return type from:
template <typename T>
T VectorVolume(const T x, const T y, const T z) {
  return x * x + y * y + z * z;
}

template<class R, class... ARGS>
std::function<R(ARGS...)> make_func(R(*ptr)(ARGS...)) {
  return std::function<R(ARGS...)>(ptr);
}

// This function fails to compile:
template <typename T>
typename decltype(make_func(&VectorVolume<param_vector<T>>))::result_type func(const T& dir) {
  return VectorVolume(dir.x, dir.y, dir.z);
}

int main() {
  const Vector3f64 foo{ 10.0, 10.0, 10.0 };

  std::cout << func(foo) << std::endl;
}

make_func来自SergyA's answer,我想创建一个std::function,所以我可以找到一个返回类型,而无需明确声明VectorVolume所使用的参数。但是我从版本15.6.7中得到了这个错误:

  

错误C2039:result_type:不是'global名称空间'的成员   错误C2061:语法错误:标识符func   错误C2143:语法错误:在;之前缺少{   错误C2447:{:缺少函数标头(旧式的正式列表?)   错误C3861:func:找不到标识符

这在g ++中的上可以正常工作:https://ideone.com/PU3oBV如果我不将using语句作为模板参数传递,它甚至可以在上正常工作:

template <typename T>
typename decltype(make_func(&VectorVolume<double>))::result_type func(const T& dir) {
    return VectorVolume(dir.x, dir.y, dir.z);
}

这几乎与我在这里解决的问题相同:Templated usings Can't be Nested in Visual Studio不幸的是,在那种情况下,我可以将函数构造替换为result_of调用。在这种情况下,我只是看不到如何重新设计make_func来解决此错误。有人知道解决方法吗? (除了升级到15.9.5确实可以解决此问题。)

2 个答案:

答案 0 :(得分:1)

作为解决方法,您可以简单地做到:

template <typename T>
auto func(const T& dir)
-> decltype(VectorVolume(dir.x, dir.y, dir.z))
{
    return VectorVolume(dir.x, dir.y, dir.z);
}

答案 1 :(得分:0)

您实际上只对function::result_type感兴趣,因此实际上无需经过返回function的错误路径。只需返回结果类型并在其上执行decltype(您甚至不需要定义函数,因为您实际上并未调用它。)类似这样的东西:

template <typename R, typename... ARGS>
R make_func(R(*)(ARGS...));

然后直接使用返回类型:

template <typename T>
decltype(make_func(&VectorVolume<param_vector<T>>)) func(const T& dir) {
    return VectorVolume(dir.x, dir.y, dir.z);
}

这在Visual Studio 15.6.7上非常有用,并且额外的好处是完全兼容:https://ideone.com/gcYo8x