gpt4 book ai didi

Why can't I specialize a template with an alias template in the return type in MSVC?(为什么我不能在MSVC中用返回类型中的别名模板专门化模板?)

转载 作者:bug小助手 更新时间:2023-10-22 18:18:34 27 4
gpt4 key购买 nike



MSVC refuses to compile this:

MSVC拒绝编译此:


#include <type_traits>

struct G { void operator()() const { } };

template<class T>
using MyTrait = std::is_void<T>;

struct S
{
template<class F>
std::enable_if_t<MyTrait<decltype(std::declval<F>()())>::value> run(F &&);
};
template<>
void S::run(G &&);

with the error:

带有错误:


<source>(14): error C2910: 'S::run': cannot be explicitly specialized
<source>(16): error C2760: syntax error: 'int' was unexpected here; expected ';'

But Clang and GCC compile it just fine. And they all compile it fine if I say std::is_void instead of MyTrait.

但是Clang和GCC编译得很好。如果我说std::is_void而不是MyTrait,他们都可以编译它。


Why is this? Is it a compiler bug, or is there something in the language that causes this problem?

为什么会这样?是编译器错误,还是语言中有什么原因导致了这个问题?


更多回答

hmm.. there is slight issue that argument of run is a forwarding reference. You specialize it as a rvalue reference, is that intended? Cannot reproduce this, which version of MSVC reports an error? /std:c++17 takes care of it for mine.

优秀答案推荐

This is a compiler bug. Defining explicit specializations of member function templates is perfectly legal.

这是一个编译器错误。定义成员函数模板的显式专业化是完全合法的。


std::enable_if_t<MyTrait<decltype(std::declval<F>()())>::value> is ultimately an alias for void with SFINAE, and the use of aliases shouldn't prevent specialization.

std::enable_if_t<MyTrait<decltype(std::declval<F>()())>::value>最终是带有SFINAE的void的别名,使用别名不应妨碍专业化。



In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers.
Specifically, this is done for explicit instantiations, explicit specializations, and certain friend declarations.



- [temp.deduc.decl] p1

-[除尘温度下降]p1


The process to determine whether the full specialization void S::run(G&&) matches the member function template is the same as if you had called S::run(g) where g is an argument of type G.

确定完全专用化的void S::run(G)是否与成员函数模板匹配的过程与调用S::run(G)时的过程相同,其中G是G类型的参数。


During this process, std::enable_if_t<MyTrait<decltype(std::declval<F>()())>::value> where F = G would turn into void.

在此过程中,std::enable_if_t<MyTrait<decltype(std::declval<F>()())>::value>,其中F=G将变为void。


It's worth noting that your example does compile with:

值得注意的是,您的示例编译时使用了:


template<class F>
std::enable_if_t<MyTrait<decltype(G{}())>::value> run(F&&);

... which is pretty much the same thing, and MSVC is being inconsistent here.

……这几乎是一样的事情,MSVC在这里不一致。


Note on MSVC versions


MSVC 19.35 compiles this, but more recent versions raise an error. I was unable to find a bug report for this issue, perhaps because it is relatively recent and no one has noticed/reported it yet.

MSVC 19.35对此进行编译,但最近的版本会引发一个错误。我找不到这个问题的错误报告,可能是因为它相对较新,还没有人注意到/报告它。


Bug report


I've submitted a bug report for this issue.

我已经为这个问题提交了一份错误报告。


更多回答

Much appreciation for submitting the bug report to Microsoft! I think it's also worth noting that another workaround for this problem is to derive from the type-trait instead of aliasing it, as in: template<typename T> struct MyTrait : std::is_void<T> {};

非常感谢您向Microsoft提交错误报告!我认为还值得注意的是,这个问题的另一个解决方法是从类型特征派生,而不是对其进行别名,如:template<typename T>struct MyTrait:std::is_void<T>{};

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com