Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic template instantiation

Tags:

c++

templates

Given the class template

template<class T>
struct A {
    A( const T & x );
};

I would like to instantiate objects of this class without writing out the actual type T, because this is typically a clumsy type resulting from some sort of expression templates and lambda functions. One way to accomplish this would be

template<class T>
A<T> create_A( const T& t ){ 
    return A<T>( t );
}

int main(){
    auto a = create_A( complicated_expression );
}

Here I never wrote the actual type of the expression, but this creates a copy of A and won't work without a copy constructor. I don't have a copy (or move) constructor. What I'm looking for is something like

A a( complicated_expression );

Clean and simple, and the compiler should be able to figure out the actual type. Unfortunately this isn't valid C++. So what would be the best valid C++ syntax to accomplish the same thing? Currently I'm doing this:

auto x = complicated_expression;
A<decltype(x)> a(x);

But this seems unnecessary verbose. Is there a better way to do this?

like image 737
pentadecagon Avatar asked May 07 '14 18:05

pentadecagon


People also ask

How do I force a template instantiation?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.

What is a template instantiation?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation to handle a specific set of template arguments is called a specialization.

Is it necessary to instantiate a template?

In order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).

What is implicit instantiation?

Implicit instantiation means that the compiler automatically generates the concrete function or class for the provided template arguments. In general, the compiler also deduces the template arguments from the function's arguments. In C++17, the compiler can also deduce the template arguments for class templates.


2 Answers

The code

template<class T>
A<T> create_A( const T& t ){ 
    return A<T>( t );
}

int main(){
    auto a = create_A( complicated_expression );
}

formally requires copy or move constructor to be defined and available, but any reasonable compiler will be able to optimize it away using copy elision rule. It is the standard idiom used widely across the standard library (e.g. std::make_pair).

like image 72
Jan Hudec Avatar answered Oct 18 '22 01:10

Jan Hudec


Well, if your compiler is MSVC, this will work:

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

No such luck with clang and g++, though.

Assigning a result returned by value to a const reference is perfectly legal, by the way, and has its uses. Why MSCV avoids checking for type being moveable/copyable (even though it would optimise it away) is a mystery to me and likely a bug. But, it'd kinda work in your case if you need to do it this way.

EDIT: alternatively, if you are not afraid to bring the wrath of C++ gods upon yourself, you can transform create_A into a macro:

#define create_A(x) (A<decltype(x)>(x))

Now it shall work on all compilers.

EDIT2: as @dyp suggested, this answer can be improved further:

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

It will work on all C++11 compilers.

like image 40
gwiazdorrr Avatar answered Oct 17 '22 23:10

gwiazdorrr