自动模板实例化

时间:2014-05-07 18:00:50

标签: c++ templates

给出类模板

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);

但这似乎没有必要冗长。有更好的方法吗?

3 个答案:

答案 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错误。