在 Visual Studio 2019 中使用枚举作为模板参数时出现错误 C2440 和 C2973

问题描述

在使用 Visual Studio 2019 编译此代码时出现两个错误 C2440 和 C2973:

#include <iostream>
#include <array>

enum class First {
    SOME_VALUE,OTHER_VALUE
};

enum class Second {
    PRIME,BIS
};


template<First FirsT_VAL>
struct FirstData {
    int i;
};

template<Second SECOND_VAL>
struct SecondData {
    long l;
};

template<First FirsT_VAL,Second SECOND_VAL>
class Data :public SecondData<SECOND_VAL>,public FirstData<FirsT_VAL> {

};

template<First FirsT_VAL>
struct WithFirstData {
    virtual const FirstData<FirsT_VAL >& getData() = 0;
    virtual ~WithFirstData() = default;
};

template<Second SECOND_VAL>
struct WithSecondData {
    virtual const SecondData<SECOND_VAL>& getData() = 0;
    virtual ~WithSecondData() = default;
};

template<First FirsT_VAL,Second SECOND_VAL>
class WithData : public WithFirstData<FirsT_VAL>,public WithSecondData<SECOND_VAL> {

public:
    const First First;
    const Second Second;
private:

    const Data<FirsT_VAL,SECOND_VAL> data;
public:

    virtual const Data<FirsT_VAL,SECOND_VAL>& getData() {
        return data;
    }

    template<typename ... DataArgs>
    WithData(DataArgs &&... data) :First(FirsT_VAL),Second(SECOND_VAL),data(std::forward<DataArgs>(data)...) {    }

    virtual ~WithData() {};
};

class ConcreteWithData : public WithData<First::SOME_VALUE,Second::BIS> {
public:
    ConcreteWithData() : WithData() {
    }
};

std::ostream& operator<<(std::ostream& ostream,const ConcreteWithData& o) {
    ostream << static_cast<int>(o.First);
    return ostream;
}
int main() {

    ConcreteWithData ev;
    std::cout << "Hello World!\n" << ev;
}

错误消息除外:

1>C:\[...]\Test.cpp(55): error C2440: 'specialization': cannot convert from 'int' to 'First'
1>C:\[...]\Test.cpp(55): message : Conversion to enumeration type requires an explicit cast (static_cast,C-style cast or function-style cast)
1>C:\[...]\Test.cpp(55): error C2440: 'specialization': cannot convert from 'int' to 'Second'
1>C:\[...]\Test.cpp(55): message : Conversion to enumeration type requires an explicit cast (static_cast,C-style cast or function-style cast)
1>C:\[...]\Test.cpp(55): error C2973: 'Event': invalid template argument 'int'
1>C:\[...]\Test.cpp(44): message : see declaration of 'Event'
1>C:\[...]\Test.cpp(44): error C2440: 'specialization': cannot convert from 'int' to 'First'
1>C:\[...]\Test.cpp(44,36): message : Conversion to enumeration type requires an explicit cast (static_cast,C-style cast or function-style cast)
1>C:\[...]\Test.cpp(44): error C2440: 'specialization': cannot convert from 'int' to 'Second'
1>C:\[...]\Test.cpp(44,70): message : Conversion to enumeration type requires an explicit cast (static_cast,C-style cast or function-style cast)
1>C:\[...]\Test.cpp(44,1): error C2973: 'WithSecondData': invalid template argument 'int'
1>C:\[...]\Test.cpp(38): message : see declaration of 'WithSecondData'

有趣的是,这在 gcc (g++.exe (Rev6,Built by MSYS2 project) 10.2.0) 下编译没有问题。 谁错在这里?我做了一些编译器不应该理解的事情;或 vs 编译器无法正确理解枚举;或者 gcc 允许它不应该的东西?

编辑 2:

如果我将它重构为无作用域的枚举和整数作为模板参数,它就会编译,所以有一个变通方法,但我希望能够使用有作用域的枚举。而且,更重要的是,我很想首先了解出了什么问题。

编辑 1:

原始代码有点大,我把它简化了一点,但基本上我想要实现的是根据不同的枚举值对 FirstData 和 SecondData 的不同数据进行专业化。因此,我可以在引用不同的具体实现时使用对 WithFirstData<SOME_VALUE> WithSecondData<PRIME> 的引用,并确保这些实现具有我正在寻找的数据。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)