MSVC:具有模板化转换运算符和多重继承的错误

问题描述

我有以下代码无法与MSVC一起编译。使用gcc,clang和icc可以正常编译。我想这是个错误,对吧?

您有/知道一些解决方法吗?

#include <type_traits>

struct A
{
    template <
        typename C,typename = std::enable_if_t<std::is_same_v<C,int>>
    >
    operator C() const{
        return 12;
    }
};

struct B
{
    template <
        typename C,char>>,typename F = int
    >
    operator C() const
    {
        return 'A';
    }
};

struct AB : A,B
{
};

int main(){
    AB ab;
    int i = ab;
    char c = ab;
}

错误文本为:

example.cpp

<source>(34): error C2440: 'initializing': cannot convert from 'AB' to 'char'

<source>(34): note: No user-defined-conversion operator available that can perform this conversion,or the operator cannot be called

Compiler returned: 2

我已经向Microsoft发布了bug report

godbolt上查看此处

解决方法

这似乎确实是MSVC中的错误。在操作员模板推导过程中似乎不考虑最后一个基数。例如。

struct AB : A,B // -> only A's templated operator considered
struct AB  : B,A // -> only B's templated operator considered

在您的情况下,您可以删除模板化运算符并直接使用类型(Live)(在这种情况下,使用模板没有多大意义):

#include <type_traits>

struct A
{
    operator int() const{ return 12;}
};

struct B
{
    operator char() const { return 'A'; }
};

struct AB : A,B
{
};

int main(){
    AB ab;
    int i = ab;
    char c = ab;
}

或者您可以改为使用类模板,类似(Live):

#include <type_traits>

template <typename T,typename = std::enable_if_t<std::is_integral_v<T>>>
struct A
{
   
    operator T() const{
        return 12;
    }
};

template <typename T,typename = std::enable_if_t<std::is_same_v<T,char>>>
struct B
{
    operator T() const
    {
        return 'A';
    }
};

struct AB : A<int>,B<char>
{
};

int main(){
    AB ab;
    int i = ab;
    char c = ab;
}

或者您可以在单个类(Live)中重载模板化歌剧演员:

struct A
{
    template <
        typename C,typename = std::enable_if_t<std::is_same_v<C,int>>
    >
        operator C() const {
        return 12;
    }

    template <
        typename C,char>>,typename F = int
    >
        operator C() const
    {
        return 'A';
    }
};


struct AB : A
{
};

int main() {
    AB ab;
    int i = ab;
    char c = ab;
}
,

我找到了workaround

在这里您可以看到我的解决方案。我更改了继承层次结构,并引入了转发转换运算符:

DBHelper