Given:
//hpp
template <typename T>
struct Demo {
template<typename U>
U convert(const T &t);
};
//cpp
template <typename T>
template <typename U>
U Demo<T>::convert(const T &t) {
return static_cast<U>(t);
}
how do I explicitly instantiate the template in the cpp? (e.g. T is double, U is int)
template int Demo<double>::convert<int>(const double &);
Related
I have a template class alpha_x give as,
template <typename T,typename U>
struct alpha_x {
const T & alpha;
const Scalar<U> & x;
alpha_x(const T & a_, const Scalar<U> & x_) : alpha(a_), x(x_) {};
};
I have another class with an overload for operator =
template <typename T>
class Scalar{
...
template <typename U,typename V>
const Scalar<T> & operator = (alpha_x<U,V> c);
...
}
When we try to define this function,
template <typename T,typename U,typename V>
const Scalar<T> & Scalar<T>::operator = (alpha_x<U,V> c){
//do something...
}
Now this gives an error "Too many template parameters in template redeclaration". How do I sort this out?
T template parameter is a class Scalar's template parameter. Thus it needs to be specified in a separate template parameter list.
Following would work:
template <typename T>
template <typename U, typename V>
const Scalar<T> & Scalar<T>::operator = (alpha_x<U,V> c){
// do something...
}
So I have a ton of functions similar to these:
template <typename T>
bool Zero(const T, const T, const T);
template <typename T>
T One(const T, const T, const T, bool);
template <typename T>
T Three(const T, const T, const T, const T, const T, const T);
For each of these functions I have a wrapper which uses the return type of these functions so it looks something like this:
template <typename T>
decltype(Zero<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ZeroWrapper(const T);
template <typename T>
decltype(One<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), bool())) OneWrapper(const T);
template <typename T>
decltype(Three<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ThreeWrapper(const T);
As you can see all those decltype(declval<T>().x)'s get disgustingly hard to read. Can I template a using or is there some standard function which will allow me to extract the return type from a function pointer without passing the argument types to decltype or result_of? So something like this:
template <typename T>
foo_t<Zero<decltype(declval<T>().x)>> ZeroWrapper(const T);
template <typename T>
foo_t<One<decltype(declval<T>().x)>> OneWrapper(const T);
template <typename T>
foo_t<Three<decltype(declval<T>().x)>> ThreeWrapper(const T);
Can I template a using or is there some standard function which will allow me to extract the return type from a function pointer without passing the argument types to decltype or result_of?
Yes!
#include <tuple>
#include <functional>
template<class T>
struct callable_trait
{};
template<class R, class... Args>
struct callable_trait<std::function<R(Args...)>>
{
using return_type = R;
using argument_types = std::tuple<Args...>;
};
template<auto callable>
using return_type = typename callable_trait<decltype(std::function{callable})>::return_type;
return_type<some_callable> is the type returned by some_callable when called with appropriate arguments. This uses a std::function in order to provide a specialization for each possible kind of callable (free function, function pointer, member function, functor object). This is explained in this StackOverflow answer.
In your case, you can use it like so:
template <typename T>
bool Zero(const T, const T, const T);
template <typename T>
T One(const T, const T, const T, bool);
template <typename T>
T Three(const T, const T, const T, const T, const T, const T);
template <typename T>
return_type<Zero<T>> ZeroWrapper(const T);
template <typename T>
return_type<One<T>> OneWrapper(const T);
template <typename T>
return_type<Three<T>> ThreeWrapper(const T);
Full demo
In c++17 the function object has been endowed with a Deduction Guide which allows it to determine it's type from the argument passed to the constructor. So for example, given the function int foo() in c++11 we had to do:
function<int()> bar(foo);
In c++17 bar's function<int()> type will be derived if we simply:
function bar(foo);
Thus we can use the Deduction Guide to populate a temporary function with only the signature; thereby using function's result_type to find the result of your helper funcitons:
template <typename T>
typename decltype(function(Zero<decltype(declval<T>().x)>))::return_type ZeroWrapper(const T);
template <typename T>
typename decltype(function(One<decltype(declval<T>().x)>))::return_type OneWrapper(const T);
template <typename T>
typename decltype(function(Three<decltype(declval<T>().x)>))::return_type ThreeWrapper(const T);
Live Example
I have a templated class with a templated friend function declaration that is not having its signature matched when stated in a more direct, but seemingly equivalent, expression:
link to example on online compiler
#include <type_traits>
template <typename Sig> class Base;
template <typename R, typename ... Args> class Base<R(Args...)> { };
template <typename Sig, typename T> class Derived;
template <typename Sig> struct remove_membership;
template <typename T, typename R, typename ... Args>
class Derived<R(Args...), T> : public Base<R(Args...)> {
static void bar() { }
// XXX: why are these two not equivalent, and only the 1st version successful?
template <typename T2>
friend auto foo(T2 const &) -> Base<typename
remove_membership<decltype(&std::remove_reference_t<T2>::operator())>::type> *;
template <typename T2>
friend auto foo(T2 const &) -> Base<R(Args...)> *;
};
template <typename F, typename R, typename ... Args>
struct remove_membership<R (F::*)(Args...) const> {
using type = R(Args...);
};
template <typename T>
auto foo(T const &) -> Base<typename
remove_membership<decltype(&std::remove_reference_t<T>::operator())>::type> *
{
using base_param_t = typename remove_membership<
decltype(&std::remove_reference_t<T>::operator())>::type;
Derived<base_param_t, T>::bar();
return nullptr;
}
int main(int, char **) { foo([](){}); } // XXX blows up if verbose friend decl. removed.
Inside member definitions of Derived<R(Args...), T> (for example, in the body of bar()), the types match, adding to my confusion:
static_assert(std::is_same<Base<R(Args...)>, Base<typename
remove_membership<decltype(&std::remove_reference_t<T>::operator())>::type>>::value,
"signature mismatch");
Are there rules around template class template member function (and friend function) delarations and instantiations that make these preceding declarations distinct in some or all circumstances?
template <typename T2>
void foo(T2 const &)
template <typename T2>
auto foo(T2 const &)
-> std::enable_if_t<some_traits<T2>::value>;
Are 2 different overloads. Even if both return void (when valid).
2nd overload uses SFINAE.
(and yes, template functions can differ only by return type contrary to regular functions).
Your version is not identical but similar (&std::remove_reference_t<T>::operator() should be valid)
You can use the simpler template friend function:
template <typename T, typename R, typename ... Args>
class Derived<R(Args...), T> : public Base<R(Args...)> {
static void bar() { }
template <typename T2>
friend auto foo(T2 const &) -> Base<R(Args...)>*;
};
template <typename T>
auto foo(T const &) -> Base<void()>* // friend with Derived<void(), U>
{
using base_param_t = typename remove_membership<
decltype(&std::remove_reference_t<T>::operator())>::type;
Derived<base_param_t, T>::bar();
return nullptr;
}
Demo
but you have then to implement different version of the template foo.
The problem can be reduced to:
template<class T>
struct identity {
using type=T;
};
class X {
int bar();
public:
template<class T>
friend T foo();
};
template<class T>
typename identity<T>::type foo() { return X{}.bar(); }
int main() {
foo<int>(); // error: bar is a private member of X
}
Even though we know identity<T>::type is always T, the compiler doesn't know that and would be wrong to assume so. There could be a specialization of identity<T> somewhere later in the code that resolves to some type other than T.
Therefore when the compiler sees the second declaration of foo it won't assume that it is the same friend foo declared before.
The template template argument can't be deduced for both foo and foo2.
If I remove the sfinae part, the template template argument was successfully deduced for both foo and foo2.
How to fix either the span class or foo and foo2?
Thanks.
Test (also at godbolt.org)
#include <type_traits>
template<typename T>
using enable_if_t_const = typename std::enable_if<
std::is_const<T>::value
>::type;
template<typename T, typename=void> class span;
template<typename T>
class span<T, enable_if_t_const<T>> {
public:
explicit span(const T* const data) {}
};
template <typename T, template<typename> class S>
void foo() {}
template <typename T, template<typename> class S>
void foo2(S<T>& s) {}
int main() {
int arr[] = {1};
span<const int> s(arr);
foo<const int, span>();
foo2(s);
return 0;
}
This is because, although you have a default template parameter, span isn't a template <typename> class S. It's a template <typename, typename> class S.
The easiest fix is to change it to
template <typename T, template<typename...> class S>
void foo2(S<T>& s) {}
So that you can accept any S that takes any number of types (although we only use it with one).
Demo
I have a template class that declares a friend function which itself has template parameters. The code looks like this:
template <class T>
class C;
template <class T, class U>
void func(C<T>& t);
template <class T>
class C
{
template <class U>
friend void func<T, U>(C<T>& t);
private:
template <class U>
void f()
{
}
};
template <class T, class U>
void func(C<T>& t)
{
t.f<U>();
}
But when I try to call func, I get a compilation error at the friend line:
'func': no matching overloaded function found
How can I make func<T, U> friend with C<T>?
The key issue is that the friend you declared, is not the same as the previous declaration you provided. The first expects two template parameters, but the second (friend) you defined to accept only one. Once that is resolved, everything works:
template <class T>
class C;
template <class U, class T>
void func(C<T>& t);
template <class T>
class C
{
template <class U, class TT>
friend void func(C<TT>& t);
private:
template <class U>
void f()
{
}
};
template <class U, class T>
void func(C<T>& t)
{
t.template f<U>();
}
int main() {
C<int> c;
func<bool>(c);
}
Watch it live.
Note I switched U and T up, because I assumed you may want T deduced and U explicitly specified.