【问题标题】:Template type deduction failing模板类型扣除失败
【发布时间】:2012-10-30 03:55:37
【问题描述】:

我正在使用 MSVC 9.0 并具有此功能:

class RecipientList
{
public:
    template<class T>
    void fillMessageWithRecipients( typename boost::is_base_of<MsgContent, T>::type* msg );
};

template< class T >
void RecipientList::fillMessageWithRecipients( typename boost::is_base_of<MsgContent, T>::type* msg )
{
 // do stuff
}

我想让模板类型推导在这里工作,所以我可以这样使用它:

class SomeMsg : public MsgContent {};

std::auto_ptr<SomeMsg> msg( new SomeMsg );

RecipientList recipients;
recipients.fillMessageWithRecipients( msg.get() );

但是我得到编译器错误:

错误 C2783: '无效 RecipientList::fillMessageWithRecipients(boost::is_base_of::type *)' : 无法推导出 'T' 的模板参数

我感觉这与实际传入的类型是指针类型而不是类型本身有关。知道如何在这里正确地进行类型推导吗?

提前致谢。

【问题讨论】:

  • 强制性评论:auto_ptr 已被弃用,原因有几个。你可能想看看Boost.SmartPointers
  • C++11 也提供了智能点。 See Wiki。这里不需要提升。
  • @pmr 来自您的链接:“这些模板旨在补充 std::auto_ptr 模板。”,除了迁移到 C++11(我不能做,我更喜欢在那里使用unique_ptr)。
  • @RobertDailey boost::scoped_ptrunique_ptr 没有移动语义。在这里看起来很合适。
  • @pmr 我的示例是为简单起见而设计的。在我的真实代码中,我实际上需要移动语义。不过,我完全了解其他智能指针选择。

标签: c++ templates boost template-meta-programming


【解决方案1】:

我感觉你在滥用boost::is_base_of。嵌套的type 将是true_typefalse_type。这两个作为参数都没有意义,并且您的指针将无法转换为那些。

你真正想要的:

#include <boost/type_traits/is_base_of.hpp>
#include <boost/utility/enable_if.hpp>

class MsgContent {};

class RecipientList
{
public:
    template<class T>
    typename boost::enable_if<
        typename boost::is_base_of<MsgContent, T>::type
      , void>::type
    fillMessageWithRecipients(T* t) { }
};

class SomeMsg : public MsgContent {};

int main()
{
  RecipientList recipients;
  SomeMsg m;
  recipients.fillMessageWithRecipients( &m );

  return 0;
}

【讨论】:

  • 谢谢,但是SomeMsg m 必须是指针类型,而不是引用:(
  • @RobertDailey 在我的示例中,它是一个指针。看&amp;
  • 这绝对有效,谢谢;有点尴尬,我忘记了如何使用类型特征:P
【解决方案2】:

您应该将 is_base_of 与 enable_if 一起使用。

is_base_of 本身只是谓词。

live demo

#include <boost/type_traits.hpp>
#include <boost/utility.hpp>
#include <iostream>
#include <ostream>

using namespace std;

struct Base1 {};
struct Derived1 : Base1 {};

struct Base2 {};
struct Derived2 : Base2 {};

template<typename T>
typename boost::enable_if< boost::is_base_of<Base1, T>, void >::type f(T* p)
{
    cout << "Base1" << endl;
}

template<typename T>
typename boost::enable_if< boost::is_base_of<Base2, T>, void >::type f(T* p)
{
    cout << "Base2" << endl;
}

int main()
{
    Derived1 d1;
    Derived2 d2;
    f(&d1);
    f(&d2);
}

输出是:

Base1
Base2

【讨论】:

    猜你喜欢
    • 2018-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    相关资源
    最近更新 更多