给出类模板
template<class T>
struct A {
A( const T & x );
};
我想在没有写出实际类型T
的情况下实例化此类的对象,因为这通常是由某种表达式模板和lambda函数产生的笨拙类型。实现这一目标的一种方法是
template<class T>
A<T> create_A( const T& t ){
return A<T>( t );
}
int main(){
auto a = create_A( complicated_expression );
}
这里我从未编写过表达式的实际类型,但这会创建A
的副本,如果没有复制构造函数,它将无法工作。我没有复制(或移动)构造函数。我正在寻找的是像
A a( complicated_expression );
干净简单,编译器应该能够找出实际类型。不幸的是,这不是有效的C ++。那么完成同样的事情最有效的C ++语法是什么?目前我正在这样做:
auto x = complicated_expression;
A<decltype(x)> a(x);
但这似乎没有必要冗长。有更好的方法吗?
答案 0 :(得分:3)
代码
template<class T>
A<T> create_A( const T& t ){
return A<T>( t );
}
int main(){
auto a = create_A( complicated_expression );
}
正式要求复制或移动构造函数被定义和可用,但任何合理的编译器都能够使用复制省略规则对其进行优化。它是标准库中广泛使用的标准习语(例如std::make_pair
)。
答案 1 :(得分:2)
好吧,如果您的编译器是MSVC,这将起作用:
template<class T>
struct A {
A(const T & x) {}
A(const A&) = delete;
A(A&&) = delete;
};
template <typename T>
A<T> create_A(const T& t)
{
return t;
}
const auto& a = create_A(666);
const auto& b = create_A(a);
const auto& c = create_A(b);
尽管如此,没有运气与clang和g ++。
将值返回的结果分配给const引用完全合法,顺便说一下,has its uses。为什么MSCV避免检查可移动/可复制的类型(即使它会优化它)对我来说是一个谜,可能是一个bug。但是,如果您需要这样做,它会在您的情况下有所作为。
编辑:或者,如果你不害怕将C ++神的愤怒带给自己,你可以将create_A
转换为宏:
#define create_A(x) (A<decltype(x)>(x))
现在它适用于所有编译器。
EDIT2:正如@dyp建议的那样,这个答案可以进一步改进:
template <typename T>
A<T> create_A(const T& t)
{
return { t };
}
auto&& a = create_A(666);
auto&& b = create_A(a);
auto&& c = create_A(b);
它适用于所有C ++ 11编译器。
答案 2 :(得分:0)
您尝试实施的技术称为template argument deduction。
所以,我认为你不能做出类似的事情:
A a( complicated_expression );
由于此处A
是模板的名称,模板参数推断仅在函数中进行。不在课堂上。使用上面的行,您将无法避免missing template arguments
错误。