模板和铸造操作员

发布于 2024-08-29 03:31:54 字数 401 浏览 3 评论 0原文

此代码可以在 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: In member function `T Foo::get() const':
test.cpp:6:错误:“const class Foo”没有名为“operator T”的成员

This code compiles in CodeGear 2009 and Visual Studio 2010 but not gcc. Why?

class Foo
{
public:
    operator int() const;

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

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

The error message is:

test.cpp: In member function `T Foo::get() const':
test.cpp:6: error: 'const class Foo' has no member named 'operator T'

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

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

发布评论

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

评论(4

沉默的熊 2024-09-05 03:31:54

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

两个名字相同如果

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

因此,在运算符关键字之后指定的类型名称不必以任何方式进行词法匹配。您可以应用以下解决方法来强制 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(); 
    }
};

It's a bug in G++. operator T is an unqualified dependent name (because it has T in it and lookup will thus be different depending on its type). As such it has to be looked up when instantiating. The Standard rules

Two names are the same if

  • ...
  • they are the names of user-defined conversion functions formed with the same type.

Thus the type name specified after the operator keyword doesn't have to match lexically in any way. You can apply the following work-around to force GCC treating it as a dependent name

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(); 
    }
};
奈何桥上唱咆哮 2024-09-05 03:31:54

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

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

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

I'm not sure what the exact rules for the names of C++ operators are, but I believe it's trying to call operator T() instead of operator int(). Why not just use a cast:

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

I haven't tested this but I believe this will accomplish more or less the same thing. If not, there should be a way to accomplish this without having to call operator T() directly. That's what overloaded operators are for, after all.

丑丑阿 2024-09-05 03:31:54

如果我将代码稍微修改为:

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

我会通过 GCC 得到以下结果:


'operator T' 没有参数
取决于模板参数,因此
“operator T”的声明必须是
可用(如果您使用
'-fpermissive',G++将接受你的
代码,但允许使用
不推荐使用未声明的名称)

但如果您要使用 -fpermissive,整个事情只有在 T = int 时才有效。

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

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

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

If I modify the code slightly to this:

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

I get the following with GCC:

there are
no arguments to 'operator T' that
depend on a template parameter, so a
declaration of 'operator T' must be
available (if you use
'-fpermissive', G++ will accept your
code, but allowing the use of an
undeclared name is deprecated)

But if you were to use -fpermissive, the whole thing would only work if T = int

On the other hand, why not do:

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

That's sort of the point of the conversion operator.

方圜几里 2024-09-05 03:31:54

我对此的用例有点好奇。我想是这样,你可以说:

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

但为什么不说:

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

键入的时间稍长(尽管可以使用 C 转换表示法),但不需要任何跳圈。

I'm s bit curious about the use case for this. I suppose it is so you can say:

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

but why not say:

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

which is slightly longer to type (though one could use the C cast notation), but doesn't need any hoop jumping.

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