如何将一个模板类转换为另一个模板类?

use*_*989 3 c++

这个问题最好用例子说明

template <typename T>
struct expression {
};

template <typename T>
struct variable {
    operator expression<T>() const {
        return {};
    }
};

template <typename T>
struct member_variable {
    template <typename U>
    void operator=(const expression<U>&) {}
};

int main() {
    variable<int> a;
    member_variable<float> b;
    b=a;
}
Run Code Online (Sandbox Code Playgroud)

就目前而言,不能使用赋值运算符,因为推导存在问题U(至少我认为这是错误告诉我的).如何编译代码?我也尝试过为expression这种方法创建一个转换构造函数variable,但也没有用.我想避免继承expression,因为它在实践中比其他两个更重.

operator=*是其他高级用法,如添加的立场operator*(expression<T>, expression<U>),并能与调用它们a*b.

我尝试过Clang trunk(8.0.0)和GCC trunk(9.0.0)-std=c++17,以及MSVC 15.9.3.

Clang消息:

prog.cc:28:6: error: no viable overloaded '='
    b=a;
    ~^~
prog.cc:20:8: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'variable<int>' to 'const member_variable<float>' for 1st argument
struct member_variable {
       ^
prog.cc:20:8: note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'variable<int>' to 'member_variable<float>' for 1st argument
struct member_variable {
       ^
prog.cc:22:10: note: candidate template ignored: could not match 'expression' against 'variable'
    void operator=(const expression<U>&) {}
         ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

GCC消息:

prog.cc: In function 'int main()':
prog.cc:28:7: error: no match for 'operator=' (operand types are 'member_variable<float>' and 'variable<int>')
   28 |     b=a;
      |       ^
prog.cc:22:10: note: candidate: 'template<class U> void member_variable<T>::operator=(const expression<U>&) [with U = U; T = float]'
   22 |     void operator=(const expression<U>&) {}
      |          ^~~~~~~~
prog.cc:22:10: note:   template argument deduction/substitution failed:
prog.cc:28:7: note:   'variable<int>' is not derived from 'const expression<T>'
   28 |     b=a;
      |       ^
prog.cc:20:8: note: candidate: 'constexpr member_variable<float>& member_variable<float>::operator=(const member_variable<float>&)'
   20 | struct member_variable {
      |        ^~~~~~~~~~~~~~~
prog.cc:28:7: note:   no known conversion for argument 1 from 'variable<int>' to 'const member_variable<float>&'
   28 |     b=a;
      |       ^
prog.cc:20:8: note: candidate: 'constexpr member_variable<float>& member_variable<float>::operator=(member_variable<float>&&)'
   20 | struct member_variable {
      |        ^~~~~~~~~~~~~~~
prog.cc:28:7: note:   no known conversion for argument 1 from 'variable<int>' to 'member_variable<float>&&'
   28 |     b=a;
      |       ^
Run Code Online (Sandbox Code Playgroud)

*正如所指出的那样,通常会operator=返回T&,但是我这个类的用例(至少目前为止)不允许链接.

Lig*_*ica 7

您正在尝试调用函数模板实例化,该实例化需要进行expression<U>后推导U.U但是,没有推论,因为你没有通过expression<U>.你通过了variable<int>.确实variable<int>可以转换为expression<int>,但你没有触发它.在尝试转换之前,扣除失败(因为如何从完全不同的类型推断出它?).

要快速解决,b=expression<int>(a) 应该解决它.你可以考虑decay()为你做一个函数来实现这个功能,实际上是你自己的左值到右值的转换!这可能就像你可以做到的那样简洁,没有进一步的架构变化.

除此之外,我没有为您提供具体的解决方案,只是说您需要根据您的要求重新考虑这个类设计.