MSVC对此代码感到满意,但GCC并不那么热衷

Rob*_*son 3 c++ templates

此代码在MSVC(19.00.23918)中编译,但GCC不喜欢它,除非我在调用Detach_Internal()时使用this-> access to member operator.

GCC是否抓住了MSVC不存在的潜在错误?作为一般规则,在引用基类中的函数时始终使用this->更好吗?

注意GCC将使用-fpermissive编译它.

#include <memory>

namespace Events
{
    template<typename T>
    class EventBase
    {
    protected:

        void Detach_Internal(std::weak_ptr<void> const & p)
        {

        }
    };

    template<typename T>
    class Event : public EventBase<T>
    {
    public:

        void Detach(std::weak_ptr<void> const & p)
        {
            Detach_Internal(p);
        }
    };
}


int main(void)
{
    auto event = std::make_unique<Events::Event<void()>>();    
}
Run Code Online (Sandbox Code Playgroud)

33:30:错误:'Detach_Internal'没有依赖于模板参数的参数,因此'Detach_Internal'的声明必须可用[-fpermissive]

son*_*yao 8

GCC是否在这里发现了VS不存在的潜在错误?作为一般规则,在引用基类中的函数时始终使用this->更好吗?

GCC是正确的.您应该this->在依赖基类中引用名称时添加(即EventBase<T>,这取决于模板参数T).

否则作为非Detach_Internal依赖名称,将不会在依赖基类中查找EventBase<T>.

要解决此问题,可以使名称Detach_Internal依赖,然后在实例化时查找,此时确切的基类模板特化是固定的.例如

this->Detach_Internal(p);
Run Code Online (Sandbox Code Playgroud)
EventBase<T>::Detach_Internal(p);
Run Code Online (Sandbox Code Playgroud)
using EventBase<T>::Detach_Internal;
Detach_Internal(p);
Run Code Online (Sandbox Code Playgroud)

  • 从某种意义上说,这不是一个"错误",而是在20年后仍然"尚未实施".[8月发布的发行说明](https://blogs.msdn.microsoft.com/vcblog/2017/08/11/c17-features-and-stl-fixes-in-vs-2017-15-3/ )说*"VS 2017 15.3中部分实现了两阶段名称查找,很快就会有详细的博客文章."*. (4认同)
  • @Robinson:是的,这是一个标准合规性问题,特别是与"两阶段模板查找"相关.微软在它们成为标准的一部分之前支持C++中的模板,并且从未完全更新其编译器的特定方面以遵循(不同的)标准规则.由于他们说现有的模板查找代码有多复杂,因此预计两阶段模板查找是他们最后做的事情. (3认同)