首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板参数替换失败,并且未完成隐式转换。

模板参数替换失败,并且未完成隐式转换。
EN

Stack Overflow用户
提问于 2020-02-26 09:27:19
回答 2查看 92关注 0票数 1
代码语言:javascript
复制
#include <type_traits>

template<bool Const>
struct view_tpl {
    using value_type = std::conditional_t<Const, const int, int>;
    value_type* ptr;

    view_tpl() = default;
    view_tpl(const view_tpl<false>& other) : ptr(other.ptr) { }
};

using view = view_tpl<false>;
using const_view = view_tpl<true>;

void read(const const_view& vw) { }

int main() {
    view vw;
    read(vw);
}

这段代码定义了一个const和一个非const视图类型,这两者都是view_tpl<Const>模板的别名。应该是这样,view可以隐式地转换为const_view,而不是相反。

它的Consttrue,定义的复制构造函数支持这一点,编译器生成一个额外的默认复制构造函数。如果Constfalse,则定义的复制构造函数将替换默认的复制构造函数。

当调用f(vw)时,应该发生这种隐式转换。

它在上面的代码中正确工作。

但是,如果我向模板(int N)添加一个参数,并将f和两个类型的别名转换为模板,那么它就不再起作用了:

代码语言:javascript
复制
#include <type_traits>

template<int N, bool Const>
struct view_tpl {
    using value_type = std::conditional_t<Const, const int, int>;
    value_type* ptr;

    view_tpl() = default;
    view_tpl(const view_tpl<N, false>& other) : ptr(other.ptr) { }
};

template<int N> using view = view_tpl<N, false>;
template<int N> using const_view = view_tpl<N, true>;

template<int N>
void read(const const_view<N>& vw) { }

int main() {
    view<0> vw;
    read(vw);
}

编译器没有执行view_tpl<0, true>view_tpl<0, false>的转换,而是只尝试一个直接的模板替换,但是失败:

代码语言:javascript
复制
main.cpp: In function 'int main()':
main.cpp:20:12: error: no matching function for call to 'read(view<0>&)'
   20 |     read(vw);
      |            ^
main.cpp:16:6: note: candidate: 'template<int N> void read(const_view<N>&)'
   16 | void read(const const_view<N>& vw) { }
      |      ^~~~
main.cpp:16:6: note:   template argument deduction/substitution failed:
main.cpp:20:12: note:   template argument 'false' does not match 'true'
   20 |     read(vw);
      |            ^

有没有一种在不改变太多代码的情况下使其工作的方法?(真正的代码比本例更复杂)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-26 09:32:00

不幸的是,隐式转换在模板参数推导中不会被考虑。

类型推断不考虑隐式转换(除上面列出的类型调整外):这是过载分辨率的工作,稍后会发生。

您可以通过传递扣减来显式地指定模板参数,然后隐式转换将在以后很好地工作。例如:

代码语言:javascript
复制
view<0> vw;
read<0>(vw);

或者应用显式转换并将其包装到帮助器中。

代码语言:javascript
复制
template<int N>
void read(const view<N>& vw) { read(static_cast<const_view<N>>(vw)); }
票数 1
EN

Stack Overflow用户

发布于 2020-02-26 10:06:10

我们可以通过重载这两种类型显式地转换和传递给您的read( const const_view<N> )函数。

代码语言:javascript
复制
#include <type_traits>

template<int N, bool Const>
struct view_tpl {
    using value_type = std::conditional_t<Const, const int, int>;
    value_type* ptr;

    view_tpl() = default;
    view_tpl(const view_tpl<N, false>& other) : ptr(other.ptr) { }
};

template<int N> using view = view_tpl<N, false>;
template<int N> using const_view = view_tpl<N, true>;

template<int N>
void read( const const_view<N>& vw )
{
    // 
}

template<int N>
void read( const view<N>& vw )
{
    const_view<N> vw_converted { vw };

    read( vw_converted );
}

int main() {
    view<0> vw;
    const_view<1> cvw;
    read(vw);
    read(cvw);
}

在线运行

或者如果您不介意为const_view提供额外的副本

代码语言:javascript
复制
#include <type_traits>

template<int N, bool Const>
struct view_tpl {
    using value_type = std::conditional_t<Const, const int, int>;
    value_type* ptr;

    view_tpl() = default;
    view_tpl(const view_tpl<N, false>& other) : ptr(other.ptr) { }
};

template<int N> using view = view_tpl<N, false>;
template<int N> using const_view = view_tpl<N, true>;

template<int N, bool Const>
void read(const view_tpl<N,Const>& vw ) {
    view_tpl<N,true> inst { vw }; // Now it is const
                                  // But one extra copy for const_view
}

int main() {
    view<0> vw;
    const_view<1> cvw;
    read(vw);
    read(cvw);
}

在线运行

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60410602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档