2011-05-19 56 views
2

请考虑我的代码的以下简化版本。 我有一个模板类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 
} 

,虽然我工作正常m惊讶于编译器设法将参数匹配到正确的模板特化。

这个问题伴随着一些typedef s,易于使用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不能与邻perator>>解析为一个A错误的专业化。

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

+3

在第二个例子中如何声明** def **? – 2011-05-19 15:40:54

+1

功能模板不能部分专用(而且你还没有使用专门化语法),所以在你的例子中你实际上是超载。 – 2011-05-19 17:45:36

回答

4

模板特化不会通过您将分配返回值的位置推断出来。你必须显式实例正确的版本:

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

(或者不管它是什么,你需要...)

+0

不应该默认参数是否足够?我想避免在调用位置指定类型。它的作品虽然+1! – Gabriel 2011-05-19 15:43:42

+0

@Gabriel:在你的例子中,'default_value'是'def',它的类型是'A <10>',它与'A <12>'不一样! (除非我错过了一些东西。) – 2011-05-19 15:46:38

+0

除非这个类型可以从'def'中推导出来,如果它和以前一样'def',我认为它应该是可能的...... – aschepler 2011-05-19 15:46:56

1
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 ! 
0

编译器不检测的类型A12实际上是一个< 12>和使用功能

其实错误的专业化,因为你传递A<12> def;在例如(错误?),应该挑选正确的过载(请参阅我对问题的评论)。您将结果分配给​​的事实不应该影响重载分辨率。

如果你的意思是相反的(通过A12并分配给任何),那么这可能是一个编译器缺陷。这工作正常here