如何使编译器使用正确的模板专用化

How to make the compiler use the right template specialization?

本文关键字:专用 何使 编译器      更新时间:2023-10-16

请考虑以下简化版本的代码。我有一个模板类A,一个模板函数Fill,以及处理intchar等基本类型的函数的专用化,以及处理A的另一个专用化:

#include <sstream>
#include <string>
#include <iostream>
template<size_t C>
class A
{
public:
    A & operator=(std::string v) { 
        data[0] ='a';
        return *this; 
    }
    char data[C];
};
template<typename T> T Fill(std::string value, T default_value);
// Specialization for A<C>
template<size_t C>
A<C> Fill(std::string value, A<C> default_value) 
{
    if (value.empty())
        return default_value;
    A<C> result;
    result = value;
    return result;
}
// Specialization for int, double, char, etc
template<typename T>
T Fill(std::string value, T default_value)
{   
    if (value.empty())
        return default_value;
    T result;
    std::istringstream(value) >> result;
    return result;
}
void main()
{
    int abc = Fill(/*Get a string somehow*/"123", 0); // OK
    A<10> def;
    def = std::string("111");
    A<10> a;
    a = Fill(/*Get a string somehow*/"abc", def);     // OK
}

尽管我很惊讶编译器设法将参数与正确的模板专用化相匹配,但这工作正常。

问题伴随着一些typedef,可以简化A<x>的使用。这是一个简化版本:

typedef A<12> A12;
...
A<12> def12;
def12 = std::string("12");
A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def12);       // Not OK !

编译器没有检测到类型A12实际上是A<12>的,并且使用了错误的函数专用化,该函数不会编译,因为 istringstream 无法用 o perator>>解析为A

如何使其使用正确的模板专业化?

模板专用化不是通过分配返回值的位置来推断的。 您必须显式实例化正确的版本:

a12 = Fill<A<12> >("xyz", def);

(或者你需要的任何东西...

typedef A<12> A12;
...
A12 a12;
a12 = Fill(/*Get a string somehow*/"xyz", def);       // Not OK !

在此示例中,您尚未向我们展示 def的类型 .假设它与前面的例子相同,即A<10>,这肯定会失败。

在模板中,第二个参数的类型必须与返回类型匹配。试试这个:

typedef A<12> A12;
...
A12 a12;
A12 def12;
a12 = Fill(/*Get a string somehow*/"xyz", def12);       // OK !

编译器未检测到类型 A12 实际上是 A<12>并且使用了错误的函数专用化

实际上,由于您在示例中传递了A<12> def;(错误?),因此应该选择正确的重载(请参阅我对该问题的评论)。将结果分配给A12 a;的事实不应影响重载解决。

如果您的意思相反(传递A12并分配给任何内容),那么这可能是编译器的缺陷。这在这里可以正常工作。