[英]Expanding variadic types into another
我正试图通过做这样的事情将一包可变类型扩展到另一种类型。
我有一个简单的特性,当TFunction
返回TReturn
时会启用。
template<typename TReturn, typename TFunction>
using ReturnsType = enable_if_t<is_same<decltype(declval<TFunction>()()),
TReturn>::value>;
它在所有主编译器(VC ++,GCC,CLANG)中都能很好地工作。
现在我想用这种表示法创建另一个:
template<typename TReturn, typename... TFunctions>
using AllReturnsType = ???
所以只有当所有传递的函数( TFunctions...
)都返回TReturn
时才会启用它。
所以我尝试了这个实现:
template<typename TReturn, typename... TFunctions>
using AllReturnsType = void_t<ReturnsType<TReturn, TFunctions>...>;
但它在VC ++中失败(在GCC和CLANG中没问题)
代码游乐场可以在这里找到: https : //godbolt.org/g/d839wp
这是MSVC ++中的错误吗? 如何在所有编译器中使其工作?
谢谢!
编辑:我正在与MSVC团队成员联系,他们正在处理它! 这是一个确认的错误。
这是MSVC ++中的错误吗?
是的,我想是这样。
如何在所有编译器中使其工作?
不要问我为什么,但似乎,如果你通过enable_if_returns
的helper struct
,如下所示
template <typename T, typename F,
bool = std::is_same_v<T, get_return_type<F>>>
struct enIfR
{ };
template <typename T, typename F>
struct enIfR<T, F, true>
{ using type = T; };
template <typename T, typename F>
using enable_if_returns = typename enIfR<T, F>::type;
您的代码也在MSVC中编译。
以下是完整编译(MSVC)示例
#include <iostream>
#include <type_traits>
template <typename Function>
using get_return_type = decltype(std::declval<Function>()());
template <typename T, typename F,
bool = std::is_same_v<T, get_return_type<F>>>
struct enIfR
{ };
template <typename T, typename F>
struct enIfR<T, F, true>
{ using type = T; };
template <typename T, typename F>
using enable_if_returns = typename enIfR<T, F>::type;
template<typename T, typename Function>
using enable_if_returns0 = typename std::enable_if<
std::is_same<T, get_return_type<Function>>::value>::type;
template<typename T, typename... Functions>
using enable_if_all_returns = std::void_t<typename enIfR<T, Functions>::type...>;
int main()
{
constexpr auto fint = []() -> int { return 1; };
constexpr auto fstring = []() -> std::string { return "asd"; };
(enable_if_returns<int, decltype(fint)>)0; // ok
//(enable_if_returns<int, decltype(fstring)>)0; // fail on all (expected)
//(enIfR<int, decltype(fstring)>::type)0; // fail on all (expected)
(enable_if_all_returns<int, decltype(fint)>)0; // fail in MSVC (NOT expected, 'get_return_type<unknown-type>' being compiled)
//(enable_if_all_returns<int, decltype(fint), decltype(string)>)0; // fail in all (expected)
return 0;
}
我同意max66它似乎是一个MSVC错误。 如果我不得不猜测发生了什么,我会说这可能归结为MSVC仍然没有完全支持表达SFINAE。
但是,似乎他们一直在进行稳定的改进 ,并且他们对std :: result_of的实现进行了宣传以使用它。
巧合的是,您尝试使用get_return_type
实现的get_return_type
:
template<typename Function>
using get_return_type = decltype(declval<Function>()());
已经完成了std::result_of
(不建议使用)和std::invoke_result
由于最新的MSVC似乎缺乏对std::invoke_result
支持,看起来如果我们修改你的代码而不是使用std::result_of
,那么所有编译都很好:
template<class Function>
using get_return_type = typename std::result_of<Function()>::type;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.