首页 > 解决方案 > 如何将一个模板类隐式转换为另一个?

问题描述

这个问题最好用例子来说明

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;
}

就目前而言,不能使用赋值运算符,因为演绎存在问题U(至少我相信这是错误告诉我的)。如何使代码编译?我也尝试过为此需要创建一个转换构造函数,expression但这variable也不起作用。我想避免继承自expression,因为它在实践中比其他两个更重。

operator=* 代表其他高级用法,例如添加operator*(expression<T>, expression<U>)并能够使用a*b.

我已经尝试了 Clang 中继 (8.0.0) 和 GCC 中继 (9.0.0)-std=c++17以及 MSVC 15.9.3。

叮当消息:

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.

海湾合作委员会消息:

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;
      |       ^

* 正如所指出的,通常operator=返回T&,但是我对这个类的用例是(至少现在)不允许链接。

标签: c++

解决方案


您正在尝试调用一个函数模板实例化,该实例化需要一个expression<U>after deducing U。但是,没有U可推断的,因为您没有通过expression<U>. 你正在传递一个variable<int>. 确实variable<int>可以转换为expression<int>,但您没有触发它。在尝试转换之前演绎失败(因为如何从完全不同的类型中演绎出来?)。

为了快速修复,b=expression<int>(a) 应该解决它。您可以考虑制作一个decay()为您执行此操作的函数,因为实际上是您自己的左值到右值转换!在没有进一步架构更改的情况下,这可能是您可以做到的尽可能简洁。

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


推荐阅读