c++ - 简化双链转换

标签 c++ oop type-conversion

问题

我想要在类 A、B、C、D、E 之间进行转换。

转换应该逐步进行。

例如,从A到E的转换涉及A->B->C->D->E的转换。

从E到B的转换涉及转换E->D->C->B

我试图简化答案:

Doubly chained conversions between classes

但它现在无法编译。

  • 为什么以前可以,现在不行了?

  • 可以修复吗?

再次感谢。


测试(也在godbolt.org)

#include <type_traits>
#include <iostream>

template<typename Self>
struct chain_converter {
    template<typename Other, typename = std::enable_if_t<
            std::is_constructible_v<Self, Other>
    >>
    operator Other() {
        return static_cast<Self*>(this)->operator Other();
    }
};

struct B;
struct C;

struct A : chain_converter<A> { operator B(); };    
struct B : chain_converter<B> {
    operator A();    
    operator C();
};    
struct C : chain_converter<C> { operator B(); };

A::operator B() { return B(); }    
B::operator A() { return A(); }    
B::operator C() { return C(); }    
C::operator B() { return B(); }

int main() {
    std::cout << std::is_constructible_v<B, A> 
              << "\n";
    A a = C();
    C c = A();
    return 0;
}

编译器错误(来自 godbolt.org ):

<source>: In function 'int main()':

<source>:37:11: error: conversion from 'C' to non-scalar type 'A' requested

     A a = C();

           ^~~

<source>:38:11: error: conversion from 'A' to non-scalar type 'C' requested

     C c = A();

           ^~~

Compiler returned: 1

以前有效的代码(也在 coliru ):

#include <type_traits>
#include <iostream>
template <typename T1, typename T2>
struct indirect_conversion {
    template <typename T, 
              typename = std::enable_if_t<
                  std::is_constructible_v<T, T2>
              >
    >
    operator T() {
        return static_cast<T1 *>(this)->operator T2();
    }
};

struct A {};

struct B : indirect_conversion<B, A> {
    operator A() {
        std::cout << "B -> A\n";
        return A();
    }
};
struct C : indirect_conversion<C, B> {
    operator B() {
        std::cout << "C -> B\n";
        return B();
    }
};

int main() {
    A a = C();
}

结果:

C -> B
B -> A

最佳答案

 error: conversion from 'C' to non-scalar type 'A' requested

这个错误只是告诉你 C不可转换为 A .

它不可转换,因为既没有转换operator A()C ,也没有转换构造函数 A(const C&)A .

您可能希望转换运算符继承自 chain_converter<C>因为它是在工作版本中继承的,但该基实际上没有这样的转换运算符,因为 std::enable_if_t 的模板参数替换失败。替换失败,因为 std::is_constructible_v<C, A>是假的。这是错误的,因为 C不能用 A 构造争论。


您对工作代码的“简化”是行不通的。 chain_converter 的第二个模板参数是必不可少的。

关于c++ - 简化双链转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50311531/

相关文章:

python - 如何将 sha256 对象转换为整数并将其打包到 python 中的 bytearray?

javascript - 通过与 NaN 比较而不使用 isNaN() 来检查输入是否为 JavaScript 中的数字

java - 处理来自 java "unchecked conversion"的潜在运行时异常的最佳方法是什么?

C++ 派生函数与基函数

c++ - 来自 std::uniform_int_distribution 的重复值

java - 从位于另一个类中的一个类访问变量

javascript - OOP 函数中的 jquery 问题

c++ - 重载 "new"运算符

c++ - Qt JsonObjects 和初始化列表——比一层更深?

javascript - 如何修复 JavaScript 中的 "this.property is not iterable at window.onload"