给出类模板
template<class T>
struct A {
A( const T & x );
};
Run Code Online (Sandbox Code Playgroud)
我想在不写出实际类型的情况下实例化此类的对象T,因为这通常是由某种表达式模板和lambda函数产生的笨拙类型.实现这一目标的一种方法是
template<class T>
A<T> create_A( const T& t ){
return A<T>( t );
}
int main(){
auto a = create_A( complicated_expression );
}
Run Code Online (Sandbox Code Playgroud)
在这里,我从未编写过表达式的实际类型,但是A如果没有复制构造函数,这将创建一个副本并且无法工作.我没有复制(或移动)构造函数.我正在寻找的是类似的东西
A a( complicated_expression );
Run Code Online (Sandbox Code Playgroud)
干净简单,编译器应该能够找出实际的类型.不幸的是,这不是有效的C++.那么完成同样的事情最有效的C++语法是什么?目前我这样做:
auto x = complicated_expression;
A<decltype(x)> a(x);
Run Code Online (Sandbox Code Playgroud)
但这似乎没有必要冗长.有一个更好的方法吗?
好吧,如果你的编译器是 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);
Run Code Online (Sandbox Code Playgroud)
但 clang 和 g++ 就没有这样的运气了。
顺便说一句,将按值返回的结果分配给 const 引用是完全合法的,并且有其用途。为什么 MSCV 避免检查类型是否可移动/可复制(即使它会优化它)对我来说是一个谜,并且可能是一个错误。但是,如果您需要这样做,那么它对您的情况会有点用。
编辑:或者,如果你不怕给自己带来 C++ 神的愤怒,你可以转换create_A成一个宏:
#define create_A(x) (A<decltype(x)>(x))
Run Code Online (Sandbox Code Playgroud)
现在它应该适用于所有编译器。
编辑2:正如@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);
Run Code Online (Sandbox Code Playgroud)
它适用于所有 C++11 编译器。