模板化 using 不能嵌套在 Visual Studio 中
这是尽可能简化的,我可以制作一个仍然遇到错误的玩具示例:
This is about as simplified as I could make a toy example that still hit the bug:
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<typename F, typename T>
using call_t = decltype(std::declval<F>()(std::declval<T>(), std::declval<T>(), std::declval<T>()));
// This function fails to compile:
template <typename T>
call_t<decltype(&VectorVolume<param_vector<T>>), param_vector<T>> func(const T& param) {
return VectorVolume(param.x, param.y, param.z);
}
int main() {
const Vector3f64 foo{ 10.0, 10.0, 10.0 };
std::cout << func(foo) << std::endl;
}
call_t
来自 Guillaume Racicot 的回答,我想用它来寻找回报类型.但我从 visual-studio-2017 版本 15.6.7:
The call_t
is from Guillaume Racicot's answer which I wanted to use to find a return type. But I get this error from visual-studio-2017 version 15.6.7:
error C2064: term does not evaluate to a function taking 3 arguments<br>
note: see reference to alias template instantiation 'call_t<unknown-type,double>' being compiled
note: see reference to function template instantiation 'unknown-type func(const T &)' being compiled
这在 g++ 上运行良好:https://coliru.stacked-crooked.com/a/48b18b66c39486ef 它甚至可以在 visual-studio-2017 如果我没有将一个 using
语句传递给另一个:
This works fine on g++: https://coliru.stacked-crooked.com/a/48b18b66c39486ef It'll even work fine on visual-studio-2017 if I don't pass one using
statement to another:
template <typename T>
call_t<decltype(&VectorVolume<param_vector<T>>), double> func(const T& param) {
return VectorVolume(param.x, param.y, param.z);
}
有什么办法可以解决这个问题吗?
Is there a way I can work around this?
推荐答案
正如@NathanOliver 所提到的,正确的解决方案是升级到 15.9.5 并修复此问题.但除非您可以使用 result_of
或 invoke_result
在 15.6.7 上通过将 call_t
更改为:
As mentioned by @NathanOliver the right solution is to upgrade to 15.9.5 where this is fixed. But barring that you can use result_of
or invoke_result
to solve that on 15.6.7 by changing call_t
to:
template<typename F, typename T>
using call_t = result_of_t<F&&(T, T, T)>;
请注意 result_of
在 c++17 因此,如果您使用/std:c++17"或/std:c++latest"运行,这将不起作用,您将需要使用更方便:
Note that result_of
is deprecated in c++17 so if you are running with "/std:c++17" or "/std:c++latest" this won't work, you'll need to use the more convenient:
template<typename F, typename T>
using call_t = invoke_result_t<F, T, T, T>;
值得注意的是,Guillaume Racicot's answer 使用了一个优雅的 veradic 模板,它也分别用作:template<typename F, typename...Args>使用 call_t = result_of_t
template
的定义更改为:
It's worth noting that Guillaume Racicot's answer used an elegant veradic template, which also works respectively as: template <typename F, typename... Args> using call_t = result_of_t<F&&(Args&&...)>
or template<typename F, typename... Args> using call_t = invoke_result_t<F, Args...>;
if you change your definition of func
to:
template <typename T>
call_t<decltype(&VectorVolume<param_vector<T>>), param_vector<T>, param_vector<T>, param_vector<T>> func(const T& param) {
return VectorVolume(param.x, param.y, param.z);
}
相关文章