c – 在SFINAE上下文中作为模板模板参数传递的引用类型的别名模板

前端之家收集整理的这篇文章主要介绍了c – 在SFINAE上下文中作为模板模板参数传递的引用类型的别名模板前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我遇到G 6.1.0(-std = c 14开关)的以下问题,我不明白为什么编译器拒绝代码.

我有一个帮助结构体is_well_formed,它检查提供的模板模板参数是否形成良好的替代另一个提供的类型:

template<template<typename> typename R,typename T,typename = void>
struct is_well_formed : std::false_type {};

template<template<typename> typename R,typename T>
struct is_well_formed<R,T,void_t<R<T>>> : std::true_type {};

我想检查一个类型是否可引用.所以我的想法是写下列内容

// (#1)
template<class T>
using reference_t = T&;

static_assert(!is_well_formed<reference_t,void>::value,"Reference to void!?");

但是我收到一个编译错误

main.cpp: In instantiation of 'struct is_well_formed<reference_t,double>':
main.cpp:62:51:   required from here
main.cpp:54:20: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class> class R,class T,class> struct is_well_formed'
  : std::false_type {};
                    ^
main.cpp:54:20: note:   expected a class template,got 'reference_t'
main.cpp:54:20: error: type/value mismatch at argument 1 in template parameter list for 'is_well_formed<R,<template-parameter-1-3> >::is_well_formed'
main.cpp:54:20: note:   expected a class template,got 'reference_t'

或者,以下工作与相同的static_assert:

// (#2)
template<class T>
using reference_t = void_t<T&>;

此外,以下作品,真的让我困惑:

// (#3)
template<class T>
using pointer_t = T*;

static_assert(is_well_formed<pointer_t,"No pointer to void!?");

三个别名有什么区别?是否是void_t< T&>解决方案最优雅?还是可以修改is_well_formed的helper结构来支持第一个引用版本?

编辑:我使用MSVC“15”预览4和(#1)和(#3)工作包括断言测试代码.但是当我尝试(#2)void引用的断言不起作用,即信息在替换期间丢失,并且从不选择false_type重载.哪个编译器是对的?

is_well_formed帮助器对应于SFINAE上的Stack Overflow文档页面中的can_apply结构,我刚刚删除了参数包.完整示例代码

#include <utility>

// Only defined in std for C++17
template <class...>
using void_t = void;

// (#1) Compiler error during substitution in is_well_formed
template<class T>
using reference_t = T&;

// (#2) Ok,asserts work
/*
template<class T>
using reference_t = void_t<T&>;
*/

// (#3) Ok,asserts work
template<class T>
using pointer_t = T*;

template<template<typename> typename R,typename = void>
struct is_well_formed 
    : std::false_type {};

template<template<typename> typename R,void_t<R<T>>> 
    : std::true_type {};

int main(int,char**)
{
    static_assert(is_well_formed<reference_t,double>::value,"No reference to double!?");
    static_assert(!is_well_formed<reference_t,"Reference to void!?");

    static_assert(is_well_formed<pointer_t,"No pointer to double!?");
    static_assert(is_well_formed<pointer_t,"No pointer to void!?");

    return 0;
}

解决方法

这可能是一个编译器错误,用户 T.C.在看到这篇文章后在GCC Bugzilla here上报告.用户 Jarod42提出
template<class T>
using reference = decltype(std::declval<T&>());

作为MSVC15和GCC 6.1.0的有效替代方案.此外,他指出,MSVC仍然需要long void_t定义

template <class...>
struct make_void { using type = void; };

template <typename... T>
using void_t = typename make_void<T...>::type;

而不是明显的

template <class...>
using void_t = void;

这妨碍了原始帖子中的选项(#2)的工作.

原文链接:https://www.f2er.com/c/112899.html

猜你在找的C&C++相关文章