当前位置: 首页 > 知识库问答 >
问题:

void\u t在Visual Studio 2015上失败

魏明亮
2023-03-14

我不明白为什么Visual Studio 2015(静态_断言触发器)的以下测试总是失败:

#include <type_traits>
using namespace std;

template<class T> using try_assign = decltype(declval<T&>() = declval<T const&>());
template<class, class = void> struct my_is_copy_assignable : false_type {};
template<class T> struct my_is_copy_assignable<T, void_t<try_assign<T>>> : true_type {};

int main()
{
    static_assert(my_is_copy_assignable<int>::value, "fail");
    return 0;
}

这基本上是沃尔特·布朗从他的cppcon 2014演讲“现代模板元编程——简编”中void_t的示例用法的转录。

需要注意的是,这个替代版本可以工作,所以我认为问题不在于MSVC对表达式SFINAE的不完整支持。

template<class T>
using try_assign = decltype(declval<T&>() = declval<T const&>());

template<class T>
struct my_is_copy_assignable
{
  template<class Q, class = try_assign<Q>>
  static true_type tester(Q&&);
  static false_type tester(...);
  using type = decltype(tester(declval<T>()));
};

我知道std::is_copy_assignable,但我只是想更好地理解C的不同版本中可用的各种元编程技术。我在网上读了几篇关于void\t的文章,但我仍然不明白为什么这个例子失败了。

有趣的是,GCC4.8.2运行良好(使用CWG1558解决方案,这与微软的版本相同)。

这是一个已知的VisualStudio bug,还是我做错了什么?

共有2个答案

莫振
2023-03-14

这看起来确实像是VC中的SFINAE问题。目前还不支持在类模板的部分专门化的模板参数中使用依赖的decltype。它应该在VS 2015更新1中起作用。

杭英杰
2023-03-14

Walter E. Brown在CppCon 2014上还提到了以下因式分解,它允许用任意条件替换try_assign

#include <type_traits>
#include <utility>

template<class T>
using try_assign = decltype(std::declval<T&>() = std::declval <T const &>());

template<class T, template<class> class Op, class = void>
struct is_valid : std::false_type { };

template<class T, template<class> class Op>
struct is_valid<T, Op, std::void_t<Op<T>>> : std::true_type { };

template<class T>
using is_copy_assignable = is_valid<T, try_assign>;

int main()
{
    static_assert(is_copy_assignable<int>::value, "fail");
    return 0;
}

这一因子分解在VS 2015中编译为OK。现在删除是否复制\u可分配并替换为是否有效。您最终得到的代码是您提供的但未编译的代码(VS 2015)。

这表明VS 2015中存在缺陷,与CWG 1558无关。在CWG问题中,该标准不清楚别名模板专门化中未使用的参数是否会导致替换失败或被忽略。

 类似资料:
  • 我在WSO2 AS 5上部署了一个axis2服务,我使用该服务器用UT basic auth保护了该服务。我想用Axis客户机调用服务。我生成了存根并尝试了这个, 我在客户端得到这个错误, 我在这里做错了什么?在WSO2 AS中,如何为使用UT保护的服务编写axis客户机?提前谢了。

  • 描述 (Description) C库函数void free(void *ptr)释放先前通过调用calloc,malloc或realloc分配的内存。 声明 (Declaration) 以下是free()函数的声明。 void free(void *ptr) 参数 (Parameters) ptr - 这是指向先前分配有要释放的malloc,calloc或realloc的内存块的指针。 如果将

  • 描述 (Description) C库函数void abort(void)中止程序执行并直接从调用位置输出。 声明 (Declaration) 以下是abort()函数的声明。 void abort(void) 参数 (Parameters) NA 返回值 (Return Value) 此函数不返回任何值。 例子 (Example) 以下示例显示了abort()函数的用法。 #include <

  • 我在尝试编写JUnit测试用例时遇到了一个问题,并且对Mockito来说是相对较新的。 我有一个我正在模拟的类的函数,这个函数恰好是void返回类型。从模拟类调用此函数时,我的理解(和调试经验)是,它不调用原始函数。为了克服这个问题,我尝试将“when”与“thenCallRealMethod()”结合使用。 “voidFunction”充满了我不想激发的逻辑。为了避免这种情况,我将这些内容提取到

  • 描述 (Description) C库函数void *memmove(void *str1, const void *str2, size_t n) n字符从str2复制到str1 ,但对于重叠的内存块,memmove()比memcpy()更安全。 声明 (Declaration) 以下是memmove()函数的声明。 void *memmove(void *str1, const void *s

  • 描述 (Description) C库函数void *memcpy(void *str1, const void *str2, size_t n) n字符从内存区域str2复制到内存区域str1 。 声明 (Declaration) 以下是memcpy()函数的声明。 void *memcpy(void *str1, const void *str2, size_t n) 参数 (Paramet