为什么不能从 Template::Type 推导出 T?

发布于 2024-11-09 03:58:47 字数 428 浏览 4 评论 0原文

这段代码有什么问题?

#include <map>

template<typename T>
struct TMap
{
    typedef std::map<T, T> Type;
};

template<typename T>
T test(typename TMap<T>::Type &tmap_) { return 0.0; }

int _tmain(int argc, _TCHAR* argv[])
{
    TMap<double>::Type tmap;
    tmap[1.1] = 5.2;
    double d = test(tmap); //Error: could not deduce template argument for T
    return 0;
}

What is wrong in this code?

#include <map>

template<typename T>
struct TMap
{
    typedef std::map<T, T> Type;
};

template<typename T>
T test(typename TMap<T>::Type &tmap_) { return 0.0; }

int _tmain(int argc, _TCHAR* argv[])
{
    TMap<double>::Type tmap;
    tmap[1.1] = 5.2;
    double d = test(tmap); //Error: could not deduce template argument for T
    return 0;
}

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

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

发布评论

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

评论(4

宁愿没拥抱 2024-11-16 03:58:48

这是不可演绎的上下文。这就是编译器无法推导模板参数的原因。

试想一下,如果您可能有如下专门的​​ TMap

template <>
struct TMap<SomeType>
{
    typedef std::map <double, double> Type;
};

鉴于 TMap::Type,编译器将如何推导类型 SomeTypestd::map 吗?它不能。 保证您在 std::map 中使用的类型也是类型< /em> 在 TMap 中。编译器不能做出这种危险的假设。无论如何,type 参数之间可能没有任何关系。

另外,您可能将 TMap 的另一个特化定义为:

template <>
struct TMap<OtherType>
{
    typedef std::map <double, double> Type;
};

这会使情况变得更糟。现在您拥有以下内容:

  • TMap::Type = std::map
  • TMap::Type = std::map

现在问问自己:给定 TMap::Typestd::map,编译器如何知道 TSomeType 还是 OtherType?它甚至不知道它有多少这样的选择,它也不知道选择本身......

我只是为了思想实验而问你(假设它可以知道整套选择)。

That is non-deducible context. That is why the template argument cannot be deduced by the compiler.

Just imagine if you might have specialized TMap as follows:

template <>
struct TMap<SomeType>
{
    typedef std::map <double, double> Type;
};

How would the compiler deduce the type SomeType, given that TMap<SomeType>::Type is std::map<double, double>? It cannot. It's not guaranteed that the type which you use in std::map is also the type in TMap. The compiler cannot make this dangerous assumption. There may not any relation between the type arguments, whatsoever.

Also, you might have another specialization of TMap defined as:

template <>
struct TMap<OtherType>
{
    typedef std::map <double, double> Type;
};

This makes the situation even worse. Now you've the following:

  • TMap<SomeType>::Type = std::map<double, double>.
  • TMap<OtherType>::Type = std::map<double, double>.

Now ask yourself: given TMap<T>::Type is std::map<double, double>, how would the compiler know whether T is SomeType or OtherType? It cannot even know how many such choices it has, neither can it know the choices themselves...

I'm just asking you for the sake of thought-experiment (assuming it can know the complete set of choices).

筱武穆 2024-11-16 03:58:48

正是编译器错误消息所说的内容:
TMap::Type, T 不能根据
标准。这样做的动机可能不是
技术上可以实现:编译器必须
实例化所有可能的 TMap 以查看是否有一个(并且
只有一个)与您传递的类型匹配。并且有一个
无限数量的 TMap

Exactly what the compiler error message says: in
TMap<T>::Type, T is not deduceable according to the
standard. The motivation for this is probably that it isn't
technically possible to implement: the compiler would have to
instantiate all possible TMap<T> in order to see if one (and
only one) matched the type you passed. And there is an
infinite number of TMap<T>.

草莓酥 2024-11-16 03:58:48

即使您有:

TMap<SomeType>::Type = std::map<double, double>. 

但在调用 test(tmap) 之前,

TMap<double>::Type tmap;
tmap[1.1] = 5.2;
double d = test(tmap); 

您已经声明了

TMap<double>::Type tmap;

无法使用此信息的原因。 #typedef 不仅仅是简单的字符串替换。

Even you have:

TMap<SomeType>::Type = std::map<double, double>. 

But before you call test(tmap)

TMap<double>::Type tmap;
tmap[1.1] = 5.2;
double d = test(tmap); 

You already have it declared as

TMap<double>::Type tmap;

why this information can not be utilized. #typedef is not just simple string replacement.

魂牵梦绕锁你心扉 2024-11-16 03:58:48

我认为“我们不能这样做”的论点是不正确的。
如果我们稍微修改这个例子,编译器就会很高兴地为我们推导出参数。

template<typename T>
struct TMap //...

template <class T>
struct tmap_t : TMap<T>::Type {};

template<typename T>
T test(tmap_t<T> tmap) // ...

tmap_t<double> tmap;  // ...
double d = test(tmap);  // compiles just fine.

我没有看到原始示例和我的示例之间有很大差异。这里真正的问题似乎是 C++ 以不同的方式对待 typedef 和类型声明,

这是一件好事吗?

I don't think "we can't do this" argument is correct.
If we slightly modify this example, the compiler is happily deducing arguments for us.

template<typename T>
struct TMap //...

template <class T>
struct tmap_t : TMap<T>::Type {};

template<typename T>
T test(tmap_t<T> tmap) // ...

tmap_t<double> tmap;  // ...
double d = test(tmap);  // compiles just fine.

I don't see a huge difference between the original example and mine. The real issue here seems that C++ treats typedefs and type declarations differently

Is this a good thing?

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