2011-11-17 41 views
15

int x = fromString("test")不能推导出模板参数的“值类型”为什么C++不能从赋值中推导出模板类型?

int x = fromString<int>("test"):如预期

所以这里为什么编译斗争工作正常?我用各种真实的模板函数来看它,而不仅仅是这个愚蠢的例子。它必须是该语言的一个特征,但是什么?

+10

为什么是不能够转化为所谓的 “的toString” 一个int? –

+2

[此问题](http:// stackoverflow。com/questions/442026/function-overloading-by-return-type)讨论了一个类似的问题。 –

+0

它“只是不”。请注意,这是语言,而不是编译器 - 虽然实际上并未在语言中指定部分语言,因为编译器在一般情况下会变得很棘手。 –

回答

12

C++不会对返回值进行类型推断。即,它被分配给一个int的事实不用于模板参数推导。

(去掉编辑,因为别人提出的重载投解决方案了。)

+1

谢谢。我不需要这么做,这只是一个轻微的恼人的怪癖,我想明白为什么。 –

1

它看起来像你的模板有模板的返回类型不能自动推断这就是为什么你需要将其添加在这里。

+0

延迟返回类型声明(或任何它被称为)具有不同的目的。它允许你根据函数参数的类型声明返回类型。它只是推迟声明返回类型,直到参数在范围内。它不能从调用者的使用中推断出结果的类型。 – visitor

+0

感谢您的评论,我将从我的帖子中删除:-) – Firedragon

0

除了为例坏的选择(可能是很有意义的int x = to<int>("1235")而非toString),问题是,返回类型不参与重载或类型推断[1]。这样做的原因是,表现在很多地方被用在返回的类型不能推导出:

// assuming template <typename T> T to(std::string): 
// 
f(to("123"));   // where there are two overloads f(int), f(double) 
int x = 1.5 * to("123"); // T == int? T == double? 
to("123");    // now what? returned object can be ignored! 

所以决定返回类型不参与重载或类型扣除一部分。

[1]这个规则有一个例外,它是一个具有多个重载的函数指针的评估,其中重载必须由目标指针或显式类型转换来选择,但是这个只是一个例外,并不用于任何其他上下文中:

void f(); 
void f(int); 
void g(void (*)()); 
void g(void (*)(int)); 

void (*p1)() = &f;  // overload selected based on destination type 
void (*p2)(int) = &f; 
g((void (*)(int))&f); // overload selected based on explicit cast 
+0

“一个函数指针” - 包括指向成员函数的指针。 –

16

您不能根据返回类型进行推导。你可以,但是,实现具有类似的语法一种变通方法,使用重载转换运算符:

#include <iostream> 
#include <sstream> 
#include <string> 
using namespace std; 

class FromString{ 
private: 
    string m_data; 
public: 
    FromString(const char*data) : m_data(data) {} 

    template<typename T> 
    operator T(){ 
     T t; 
     stringstream ss(m_data); 
     ss >> t; 
     return t; 
    } 

}; 

template<> FromString::operator bool(){ 
    return (m_data!="false"); //stupid example 
} 

int main(){ 

    int ans = FromString("42");  
    bool t = FromString("true"); 
    bool f = FromString("false"); 

    cout << ans << " " << t << " " << f << endl; 

    return 0; 
} 

输出:

42 1 0 
+0

通用转换函数,哎!但是因为'operator ='不能成为'friend',所以我认为这是最好的解决方案+1。 – Potatoswatter

0

一个函数的返回类型依赖于重载决议,而不是相反周围。

有,工程虽然一招:operator=通常只存在等于LHS/RHS参数类型,当显式operator=定义除(不论是独立的或作为成员并不重要)。

因此,重载分辨率会找到operator=(int &, int),并查看函数的返回值是否可以转换为int。如果您返回具有operator int的临时文件,则这是可接受的分辨率(即使operator int的格式为template<typename T> operator T)。

这样:

template<typename T, typename U> 
U convert_impl(T const &t); 

template<typename T> 
struct convert_result { 
    convert_result(T const &t) : t(t) { } 
    template<typename U> operator U(void) const { return convert_impl<U>(t); } 
    T const &t; 
}; 

template<typename T> 
convert_result<T> convert(T const &t) { return t; } 
相关问题