C++模板和歧义问题

发布于 2024-08-14 07:49:34 字数 771 浏览 8 评论 0原文

我有一个指针类的子集,如下所示:

template <typename T>
struct Pointer
{
     Pointer();
     Pointer(T *const x);
     Pointer(const Pointer &x);
     template <typename t>
     Pointer(const Pointer<t> &x);

     operator T *() const;
};

最后一个构造函数的目标是允许传递子类的指针,或者基本上任何可隐式转换为 T * 的类型。这个实际的规则仅由构造函数的定义强制执行,编译器实际上无法仅通过声明来弄清楚它。如果我删除它,并尝试将 Pointer 传递给 Pointer 的构造函数,我会收到编译错误,尽管可能存在通过 <代码>运算符 T *()。

它在解决上述问题的同时,也带来了另一个问题。如果我有一个重载函数,其中一个重载采用 Pointer ,另一个重载采用 Pointer,并且我尝试使用 Pointer调用它;SubClass>,我在两个重载之间存在歧义,当然,其目的是调用后一个重载。

有什么建议吗? (希望我说得足够清楚)

I have a subset of a pointer class that look like:

template <typename T>
struct Pointer
{
     Pointer();
     Pointer(T *const x);
     Pointer(const Pointer &x);
     template <typename t>
     Pointer(const Pointer<t> &x);

     operator T *() const;
};

The goal of the last constructor is to allow to pass a Pointer of a subclass, or basically any type that is implicitly convertable to T *. This actual rule is only enforced by the definition of the constructor and the compiler can't actually figure it out by the declaration alone. If I drop it, and try to pass a Pointer<Sub> to a constructor of Pointer<Base>, I get a compile error, despite of the possible path through operator T *().

While it solves the above problem, it creates another one. If I have an overloaded function whose one overload takes a Pointer<UnrelatedClass> and the other takes Pointer<BaseClass>, and I try to invoke it with a Pointer<SubClass>, I get an ambiguity between the two overloads, with the intention, ofcourse, that the latter overload will be called.

Any suggestions? (Hopefully I was clear enough)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨光如昨 2024-08-21 07:49:34

解决您的问题的方法称为 SFINAE(替换失败不是错误)

#include "boost/type_traits/is_convertible.hpp"
#include "boost/utility/enable_if.hpp"

template<typename T>
class Pointer {
   ...
   template<typename U>
   Pointer(const Pointer<U> &x,
      typename boost::enable_if<
         boost::is_convertible<U*,T*>
      >::type* =0)
   : ...
   {
     ...
   }
   ...
};

如果 U* 可转换为 T*,则 enable_if 将有一个 typedef 成员 type 默认为 void。然后,一切都很好。如果 U* 不可转换为 T*,则缺少此 typedef 成员,替换将失败并且构造函数模板将被忽略。

这解决了您的转换和歧义问题。

回应评论:is_convertible 看起来像这样:

typedef char one;         // sizeof == 1  per definition
struct two {char c[2];};  // sizeof != 1

template<typename T, typename U>
class is_convertible {
    static T source();
    static one sink(U);
    static two sink(...);
public:
    static const bool value = sizeof(sink(source()))==1;
};

The cure for your problem is called SFINAE (substitution failure is not an error)

#include "boost/type_traits/is_convertible.hpp"
#include "boost/utility/enable_if.hpp"

template<typename T>
class Pointer {
   ...
   template<typename U>
   Pointer(const Pointer<U> &x,
      typename boost::enable_if<
         boost::is_convertible<U*,T*>
      >::type* =0)
   : ...
   {
     ...
   }
   ...
};

If U* is convertible to T* the enable_if will have a typedef member type defaulting to void. Then, everything is fine. If U* is not convertible to T* this typedef member is missing, substitution fails and the constructor template is ignored.

This solves your conversion and ambiguity problems.

In response to the comment: is_convertible looks something like this:

typedef char one;         // sizeof == 1  per definition
struct two {char c[2];};  // sizeof != 1

template<typename T, typename U>
class is_convertible {
    static T source();
    static one sink(U);
    static two sink(...);
public:
    static const bool value = sizeof(sink(source()))==1;
};
一个人练习一个人 2024-08-21 07:49:34

尝试使有问题的构造函数明确,例如:

 template <typename t>
 explicit Pointer(const Pointer<t> &x);

和/或删除operator T *() const; - 我认为这也会产生歧义。

编辑

检查std::auto_ptr接口,并与您的进行比较。至少他们解决了歧义。

Try to make the constructor in question explicit, e.g.:

 template <typename t>
 explicit Pointer(const Pointer<t> &x);

And/or remove the operator T *() const; - I think this one will also create an ambiguity.

EDIT

Check the std::auto_ptr interface, and compare with yours. At least they solved the ambiguity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文