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?
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.
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.
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).
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.
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
).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With