为什么访问 CRTP 中派生类型的静态成员可以使用 g++ 而不能使用 cl.exe?

问题描述 投票:0回答:1

我正在开发一个 C++ 项目,其中使用 CRTP 提供有关序列化对象的类型信息。我添加了一个

static constexpr TypeID TYPE_ID
并将其设置为
Derived::TYPE_ID
并开始收到有关
TYPE_ID
不是我的派生类
TestObject
的成员的编译器错误。我创建了此设置的最小版本,运行良好,但我意识到我正在使用 g++ 编译最小版本,并使用 MSVC 编译完整版本。使用 cl.exe 编译最小版本再次出现错误。

这是我的最小代码:

base.h

#ifndef BASE_H
#define BASE_H

#include <string_view>

class IBase {
public:
    virtual ~IBase() = default;
};

template<typename Derived>
class Base : public IBase {
public:
    static constexpr std::string_view TYPE_ID = Derived::TYPE_ID;
};

#endif

main.cpp

#include <iostream>

#include "base.h"

class Derived : public Base<Derived> {
public:
    static constexpr std::string_view TYPE_ID = "Derived";
};

int main() {
    std::cout << Base<Derived>::TYPE_ID << std::endl;
}

使用 cl.exe 进行编译会产生以下输出:

Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33141 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
C:\Users\Harry\temp\cpp_testing\CRTP-test-mimimal\base.h(14): error C2039: 'TYPE_ID': is not a member of 'Derived'
.\main.cpp(5): note: see declaration of 'Derived'
C:\Users\Harry\temp\cpp_testing\CRTP-test-mimimal\base.h(14): note: the template instantiation context (the oldest one first) is
.\main.cpp(5): note: see reference to class template instantiation 'Base<Derived>' being compiled
C:\Users\Harry\temp\cpp_testing\CRTP-test-mimimal\base.h(14): error C2065: 'TYPE_ID': undeclared identifier
C:\Users\Harry\temp\cpp_testing\CRTP-test-mimimal\base.h(14): error C2131: expression did not evaluate to a constant
C:\Users\Harry\temp\cpp_testing\CRTP-test-mimimal\base.h(14): note: a non-constant (sub-)expression was encountered

但是当使用 g++ 时,它编译时没有错误并按预期运行。

为什么会发生这种情况?有什么方法可以让它与 MSVC 编译器一起工作吗?

c++ templates visual-c++ g++ crtp
1个回答
0
投票

您可以使用静态函数来代替

TYPE_ID
,并通过从基类调用
Derived
实现来使用 CRTP:

#include <string_view>
#include <iostream>

class IBase {
public:
    virtual ~IBase() = default;
};

template<typename Derived>
class Base : public IBase {
public:
    static constexpr std::string_view TYPE_ID() { return Derived::TYPE_ID(); }
};

class Derived : public Base<Derived> {
public:
    static constexpr std::string_view TYPE_ID() { return  std::string_view {"Derived"}; }
};

int main() {
    std::cout << Base<Derived>::TYPE_ID() << std::endl;
}

演示

© www.soinside.com 2019 - 2024. All rights reserved.