假设我有以下模板函数:
// #include <iostream>
template< typename T >
T read( std::istream& in )
{
T x;
in >> x; // (could check for failure, but not the point)
return x;
}
它旨在像这样使用(const
从用户输入初始化变量):
// #include <string>
// std::istream& in = std::cin;
const int integer = read< int >( in );
const double decimal = read< double >( in );
const std::string word = read< std::string >( in );
...
但请注意,必须提供两次相同的类型:一次用于变量声明,一次用于调用。最好避免这种重复(另请参阅DRY 原则,“不要重复自己”),因为每个更改都必须重复,例如这样的代码:
const int integer = read< double >( in );
const double decimal = read< int >( in );
const std::string word = read< char* >( in );
编译“很好”,但可能会在运行时做坏事(尤其是第三个,这会导致警告)。
有没有办法避免类型重复?
我已经可以想到两种方法,所以与其假装我不认识它们,我会在要求更多之前迅速暴露它们:
返回类型解析器
我最近发现了“返回类型解析器”成语(来自这个问题)。所以我们可以围绕现有函数创建一个带有模板隐式转换运算符的简单类:
class Read { std::istream& m_in; public: explicit Read( std::istream& in ) : m_in( in ) { } template< typename T > operator T() const { return read< T >( m_in ); } };
我们现在可以编写如下代码:
const int integer = Read( in ); const double decimal = Read( in ); const std::string word = Read( in ); ...
其中“返回类型”是从变量类型自动推导出来的(注意:即使变量是,返回类型也不
const
是,所以这确实等同于原始代码(尤其是在可能的内联之后)。C++11
auto
从C++11开始,我们可以使用说明
auto
符作为替代,这也避免了两次命名类型,但方法是“逆向的”:const auto integer = read< int >( in ); const auto decimal = read< double >( in ); const auto word = read< std::string >( in ); ...
其中变量类型是从返回类型自动推导出来的。
还要别的吗?
现在,您知道其他选择吗?[如果您想知道,请参阅我对以下评论的回复,了解此问题的“原因”。]
谢谢你。