int x = fromString("test")
:无法推断'ValueType'的模板参数
int x = fromString<int>("test")
:按预期正常工作
为什么编译器在这里挣扎?我用各种真实的模板函数看到它,而不仅仅是这个愚蠢的例子。它必须是语言的一个特征,但是什么?
答案 0 :(得分:18)
您无法根据返回类型推断出。但是,您可以使用重载的强制转换运算符实现具有类似语法的变通方法:
#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
答案 1 :(得分:12)
C ++不对返回值进行类型推断。即,它被分配给int的事实不用于模板参数推导。
(删除了编辑,因为其他人已经提交了重载的强制转换解决方案。)
答案 2 :(得分:1)
看起来您的模板具有模板化的返回类型,无法自动推断,这就是您需要在此处添加它的原因。
答案 3 :(得分: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] 此规则有一个例外,即对具有多个重载的函数指针的求值,其中必须通过目标指针或显式选择重载cast,但这只是一个例外,并没有在任何其他上下文中使用:
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
答案 4 :(得分: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; }