繁体   English   中英

将可变参数类型扩展到另一个类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM