Doubly chained conversions between classes

2019-08-26 06:01发布

问题:

I have a series of classes A, B, C, ...

I want to define conversion between any pair of classes.

The conversion has to follow the ordering of classes in the series.


For example, a conversions from A to C has the following steps:

  1. A converts to B.
  2. B finally converts to C

Similarly, a conversion from C to A has the following steps:

  1. C to B
  2. B to A

I try to modify the answer of my last question:

Chained conversion between classes without public inheritances

But I can only get chained conversion from C to A work. Chained conversions in the opposite direction doesn't work.

How to make chained conversions in both directions work?

Test (also at godbolt.org)

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

struct B;
struct C;

struct A { operator B(); };

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

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

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

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


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

int main() {
    A a = C();
    C c = A();  // This line does not compile.
    return 0;
}

Compilation error:

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

     C c = A();  // This line does not compile.

           ^~~

回答1:

Fix by making A inherits from conversion_chain:

struct A : conversion_chain<A, B> { operator B(); };