【问题标题】:templates and casting operators模板和铸造运算符
【发布时间】:2011-02-09 21:25:32
【问题描述】:

此代码可在 CodeGear 2009 和 Visual Studio 2010 中编译,但不能在 gcc 中编译。为什么?

class Foo
{
public:
    operator int() const;

    template <typename T> T get() const { return this->operator T(); }
};

Foo::operator int() const
{
    return 5;
}

错误信息是:

test.cpp:在成员函数`T Foo::get() const'中:
test.cpp:6:错误:“const class Foo”没有名为“operator T”的成员

【问题讨论】:

  • 好吧,如果您要求转换为 int 以外的其他内容,它将不起作用。你是怎么用的?
  • 我什至还没到可以使用它的地步……它在那之前就坏了。
  • 你在任何地方都调用 Foo::get() 吗?

标签: c++ templates casting operator-overloading


【解决方案1】:

这是 G++ 中的一个错误。 operator T 是一个不合格的从属名称(因为它有 T 在其中,因此查找将根据其类型而有所不同)。因此,在实例化时必须查找它。标准规则

两个名字相同如果

  • ...
  • 它们是由相同类型组成的用户定义转换函数的名称。

因此,在 operator 关键字之后指定的类型名称不必以任何方式在词法上匹配。您可以应用以下解决方法来强制 GCC 将其视为依赖名称

template<typename T, typename>
struct identity { typedef T type; };

class Foo
{
public:
    operator int() const;

    template <typename T> T get() const { 
      return this->identity<Foo, T>::type::operator T(); 
    }
};

【讨论】:

  • 这确实有效,但它似乎是一个尴尬的工作。感谢您的帮助!
  • @Jonathan,是的,它与虚拟operator int 中断。如果您想进行虚拟通话,可以拨打static_cast&lt;typename identity&lt;Foo, T&gt;::type*&gt;(this)-&gt;operator T();
【解决方案2】:

我不确定 C++ 运算符名称的确切规则是什么,但我相信它试图调用 operator T() 而不是 operator int()。为什么不直接使用演员表:

template <typename T> T get() const { return static_cast<T>(*this); }

我没有对此进行测试,但我相信这或多或少会完成相同的事情。如果没有,应该有一种方法可以完成此操作,而无需直接调用operator T()。毕竟,这就是重载运算符的用途。

【讨论】:

  • @GMan - 不确定,留下它,因为 UncleBens 已经没有它了。
  • static_cast 是否显式调用重载的强制转换运算符?我想避免意外调用 int 而不是 long 或 double 而不是 float 等。
  • 看起来没有。我测试过了。
【解决方案3】:

如果我稍微修改一下代码:

template <typename T> T get() const { return operator T(); }

我通过 GCC 得到以下信息:

有 没有对“操作员 T”的论据 取决于模板参数,所以 'operator T' 的声明必须是 可用(如果您使用 '-fpermissive',G++ 会接受你的 代码,但允许使用 不推荐使用未声明的名称)

但是如果你要使用 -fpermissive,整个事情只有在 T = int 时才会起作用

另一方面,为什么不这样做:

template <typename T> T get() const { return *this; }

这就是转换运算符的重点。

【讨论】:

  • 因为我想显式调用特定类型的运算符,而当我的意思是 double 或 int 时,我的意思是 long 时,不允许编译器调用 float。
  • @Jonathan:我真的找不到广泛使用转换函数的理由,特别是如果你想很好地跟踪什么转换成什么。
【解决方案4】:

我对这个用例有点好奇。我想你可以这样说:

Foo f;
int x = f.get<int>();

但为什么不说:

Foo f;
int x = static_cast<int>(f);

打字稍长(尽管可以使用 C 转换符号),但不需要任何箍跳。

【讨论】:

    猜你喜欢
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 2020-09-04
    • 2012-07-16
    相关资源
    最近更新 更多