Is there any way to call a class member function that takes only 1 template argument instead of 2?
I would like to write some code like this:
template<typename T, size_t N>
void Container<int, N>::quick_sort() {
}
You cannot partial specialize a method, you could partial specialize the whole class, but require some duplication.
template<typename T, size_t N>
class Container
{
// Some code ...
void quick_sort();
};
template <typename T,size_t N>
void Container<T, N>::quick_sort()
{
// ...
}
// Class specialization
template <size_t N>
class Container<int, N>
{
// Some similar/same code...
void quick_sort();
};
template <size_t N>
void Container<int, N>::quick_sort()
{
// ...
}
As alternative, C++17 allows
template<typename T, size_t N>
class Container
{
// Some code ...
void quick_sort()
{
if constexpr (std::is_same_v<int, T>) {
// ...
} else {
// ...
}
}
};
For prior versions, regular if would probably produces error (both branches should be valid, even if not taken).
So tag dispatching is an easy approach (SFINAE is another one):
template <typename> struct Tag{};
template<typename T, size_t N>
class Container
{
private:
void quick_sort(tag<int>)
{
// ...
}
template <typename U>
void quick_sort(tag<U>)
{
// ...
}
public:
void quick_sort()
{
quick_sort(Tag<T>());
}
// Some code ...
};
Related
I want to create a function overload to partially specialize a template class. How to make this code work?
template <typename T>
struct Foo;
template <typename Result, typename ... Args>
struct Foo<Result(Args...)>
{
Result Bar()
{
Result t;
return t;
}
};
template <typename ... Args>
void Foo<void(Args...)>::Bar()
{
// do nothing;
}
If it's just a single member function that should expose different behavior if Result=void, then use tag-dispatching:
#include <type_traits>
template <typename T>
struct Foo;
template <typename Result, typename... Args>
struct Foo<Result(Args...)>
{
Result Bar()
{
return Bar(std::is_void<Result>{});
}
private:
Result Bar(std::false_type)
{
Result t;
// Do something
return t;
}
void Bar(std::true_type)
{
// Do nothing
}
};
DEMO
Alternatively, partially-specialize the whole class:
template <typename... Args>
struct Foo<void(Args...)>
{
void Bar()
{
// Do nothing
}
};
I have class like this:
template<typename T>
MyClass{
//myFunc();
}
I want to create myFunc method that return numeric value if class template is numeric and return nothing (void) when class template is not numeric.
For now, I got sth like this:
template<typename T>
MyClass{
template <typename returnT>
returnT myFunc();
}
template <typename T>
template <typename returnT>
typename std::enable_if<std::is_arithmetic<T>::value>
T MyClass<T>::myFunc()
{
return T::value;
}
template <typename T>
template <typename returnT>
typename std::enable_if<!std::is_arithmetic<T>::value>
void MyClass::myFunc()
{
//do sth
}
of course, that doesn't work. Is that a good idea to solve this problem this way? What is "smart" and working solution?
As an alternative to the constexpr if solution already supplied, here is your initial idea in it's working form.
#include <type_traits>
#include <iostream>
template<typename T>
struct MyClass{
template <typename returnT = T, std::enable_if_t<std::is_arithmetic_v<returnT>, bool> = true>
T myFunc();
template <typename returnT = T, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool> = true>
void myFunc();
};
template <typename T>
template <typename returnT, std::enable_if_t<std::is_arithmetic_v<returnT>, bool>>
T MyClass<T>::myFunc()
{
std::cout << "yo\n";
return T{};
}
template <typename T>
template <typename returnT, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool>>
void MyClass<T>::myFunc()
{
std::cout << "yay\n";
}
int main() {
MyClass<int> m;
MyClass<std::string> n;
m.myFunc();
n.myFunc();
}
The simplest way I can think of would be to just use if constexpr:
template <typename T>
class MyClass
{
auto myFunc()
{
if constexpr (std::is_arithmetic_v<T>)
{
return T{};
}
else
{
// do smth
}
}
};
If you can't use C++17, you will have to revert to some SFINAE-based approach. What that would best look like exactly depends a lot on what the actual signatures involved should be. But, for example, you could provide a partial class template specialization for the case of an arithmetic type:
template <typename T, typename = void>
class MyClass
{
void myFunc()
{
// do smth
}
};
template <typename T>
class MyClass<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
T myFunc()
{
return {};
}
};
Note that an arithmetic type cannot be a class type or enum, so I'm not sure what T::value was trying to achieve in your example code for the case of T being an arithmetic type…
I would create a helper template class to select the return type, and a helper function that uses overloading to perform the right behavior.
template <typename, bool> struct RType;
template <typename T> struct RType<T, false> { typedef void type; };
template <typename T> struct RType<T, true> { typedef T type; };
template<typename T>
class MyClass{
typedef RType<T, std::is_arithmetic<T>::value> R;
void myFuncT(RType<T, false>) {}
T myFuncT(RType<T, true>) { return 0; }
public:
typename R::type myFunc() { return myFuncT(R()); }
};
In C++ 11, can I build a template which explicitly instantiates a sequence of function templates into an array initialiser? What I want to achieve (please don't ask why I need that, because it's a long story) looks like
// The template I want to instantiate:
template<size_t N> void callbackTemplate(const int dummy) {
// Do something which needs to know 'N'.
}
// The variable I want to assign 'callbackTemplate' instantiations to:
void (*callback)(const int dummy); // This cannot be std::function, because it
// is not defined by me! It is already there and
// must be used as it is.
// This is the set of instantiations I want to prepare:
std::array<decltype(callback), 3> callbackTemplates = {
callbackTemplate<0>, callbackTemplate<1>, callbackTemplate<2>
};
The code above works as it is. What I want to change is the initialisation of the callbackTemplates array. I want the initialiser to become a template which is dependent on a compile-time constant and creates the instantiations 0..N.
The problem is somehow related to C++ static const array initialization in template class, but I did not manage to "templatise" the instantiation of the other template.
You can do this using an implementation of C++14's std::integer_sequence. Here's one.
With callback_t defined as
using callback_t = decltype (callback);
you can just pass a sequence and make use of the type deduction:
template<unsigned... Is>
array<callback_t, sizeof...(Is)> make_callback_array_impl(seq<Is...>)
{
return { callbackTemplate<Is>... };
}
template<unsigned N>
array<callback_t, N> make_callback_array()
{
return make_callback_array_impl(GenSeq<N>{});
}
live demo
This can be done with variable template specializations.
template<class>
int callbackTemplates_v;
template<std::size_t... Indicies>
std::array<decltype(callback), sizeof...(Indicies)>
callbackTemplates_v<std::index_sequence<Indicies...>> = {callbackTemplate<Indicies>...};
template<std::size_t N>
auto callbackTemplates = callbackTemplates_v<std::make_index_sequence<N>>;
Now callbackTemplates<N> is an array of N instaniations of callbackTemplate from 0..N-1.
Do you mean something as follows?
template <std::size_t ...>
struct range
{ };
template <std::size_t N, std::size_t ... Next>
struct rangeH
{ using type = typename rangeH<N-1U, N-1U, Next ... >::type; };
template <std::size_t ... Next >
struct rangeH<0U, Next ... >
{ using type = range<Next ... >; };
template <std::size_t N>
struct arrayWrapper
{
private:
std::array<decltype(callback), N> callBT;
template <std::size_t ... rng>
arrayWrapper (const range<rng...> &)
: callBT{ callbackTemplate<rng>... }
{ }
public:
arrayWrapper ()
: arrayWrapper (typename rangeH<N>::type())
{ }
};
If you can use C++14, you can throw away rangeH and range and the wrapper become simply
template <std::size_t N>
struct arrayWrapper
{
private:
std::array<decltype(callback), N> callBT;
template <std::size_t ... rng>
arrayWrapper (const std::index_sequence<rng...> &)
: callBT{ callbackTemplate<rng>... }
{ }
public:
arrayWrapper ()
: arrayWrapper (std::make_index_sequence<N>())
{ }
};
I think it's not possible but someone must know better...
template<typename T>
T Read() //T is int, char, etc
{
return read<T>();
}
template<typename T, Size>
std::array<T,Size> Read<std::array<T, Size>>()
{
return unique_read<T, Size>();
}
I guess as soon as I specify any template argument it's no longer a full specialization, and partial specialization is not allowed in functions
The only thing I could come up with is:
template<typename T>
struct _dummy
{
T Read() {
return T();
};
};
template<typename T, size_t Size>
struct _dummy<std::array<T, Size>>
{
using ArrayType = std::array<T, Size>;
ArrayType Read() {
return ArrayType();
};
};
You should use tag dispatching for this sort of job:
namespace detail {
template<class T>struct tag{};
template<class T>
T Read(tag<T>) {
return T{};
}
template<class T, std::size_t N>
std::array<T, N> Read(tag<std::array<T, N>>) {
return {1,2,3};
}
}
template<class T>
auto Read() {
return detail::Read(detail::tag<T>());
}
int main() {
Read<std::array<int,5>>();
}
The other way to do this is to defer to a function object:
template<class T>
struct reader_op {
T operator()() const {
// whatever needs to happen here
}
};
// partially specialise for array case
template<class T, size_t N>
struct reader_op<std::array<T, N>> {
std::array<T, N> operator()() const {
// whatever needs to happen here
}
};
// reader_op class type is now deduced from T
// when T is a std::array, our specialised function object will
// be used
template<typename T>
T Read() //T is int, char, etc
{
return reader_op<T>()();
}
I want to implement a compile-time foreach() which can call a given template member function N times.
Currently I have my compile-time foreach:
struct ForEach
{
template <size_t Dummy>
struct IntToType {};
typedef IntToType<true> ForEachDoNotTerminateLoop;
typedef IntToType<false> ForEachTerminateLoop;
template <size_t TIdx, size_t TCount, typename TMethod>
static void ForEachImpl(ForEachDoNotTerminateLoop, TMethod method)
{
method.Invoke<TIdx>();
ForEachImpl<TIdx + 1, TCount, TMethod>(Internal::IntToType<(TIdx + 1 < TCount)>(), method);
}
template <size_t TIdx, size_t TCount, typename TMethod>
static void ForEachImpl(ForEachTerminateLoop, TMethod method)
{
}
template <size_t TCount, typename TMethod>
static void Member(TMethod method)
{
ForEachImpl<0, TCount, TMethod>(Internal::IntToType<(0 < TCount)>(), method);
}
};
And some template class:
template <typename T, size_t TCount>
class SomeClass
{
public:
void Foo(int arg1)
{
ForEach::Member<TCount>(BarInvoker(this, arg1));
}
private:
struct BarInvoker // <-- How can I make this invoker a template to make it more flexible?
{
BarInvoker(SomeClass* instance, int arg1)
: instance(instance)
, arg1(arg1)
{}
template <size_t N>
void Invoke()
{
instance->Bar<N>(arg1);
}
int arg1;
SomeClass* instance;
};
template <size_t N>
void Bar(int arg1)
{
_data[N] = arg1;
}
int* _data;
T* _otherData;
};
Is there a way to bypass the "invoker" functor, to make it more flexible (template) and easier to use?
I don't really like to bloat my code by adding an "invoker" stub for each of my private member functions.
It would be nice to just call ForEach::Member<TCount, int>(Bar, 5);
Thanks in advance for helping me out with this template weirdness! :)
Wrapping the template function in a class and passing an instance of the class to ForEach::Call<> with arbitrary arguments to call it with, seem to be a fairly clean solution.
The ForEach::Call<>'s call looks like: ForEach::Call<N>(function_object, arguments...)
The function_object is a class that has an operator() defined as:
template <std::size_t Idx> // Current index in the for-loop.
void operator()(/* arguments... */) { /* Impl. */ }
Here is my version of the ForEach<>.
class ForEach {
public:
/* Call function f with arguments args N times, passing the current index
through the template argument. */
template <std::size_t N, typename F, typename... Args>
static void Call(F &&f, Args &&...args) {
Impl<0, N>()(std::forward<F>(f), std::forward<Args>(args)...);
}
private:
/* Forward declaration. */
template <std::size_t Idx, std::size_t End>
class Impl;
/* Base case. We've incremeneted up to the end. */
template <std::size_t End>
class Impl<End, End> {
public:
template <typename F, typename... Args>
void operator()(F &&, Args &&...) { /* Do nothing. */ }
}; // Impl<End, End>
/* Recursive case. Invoke the function with the arguments, while explicitly
specifying the current index through the template argument. */
template <std::size_t Idx, std::size_t End>
class Impl {
public:
template <typename F, typename... Args>
void operator()(F &&f, Args &&...args) {
std::forward<F>(f).template operator()<Idx>(std::forward<Args>(args)...);
Impl<Idx + 1, End>()(std::forward<F>(f), std::forward<Args>(args)...);
}
}; // Impl<Idx, End>
}; // ForEach
I've written something similar to your SomeClass to demonstrate its use.
template <std::size_t Size>
class Ints {
public:
using Data = std::array<int, Size>;
/* Call Assign, Size times, with data_ and n as the arguments. */
void AssignAll(int n) { ForEach::Call<Size>(Assign(), data_, n); }
/* Call Print, Size times, with data_ and n as the arguments. */
void PrintAll() const { ForEach::Call<Size>(Print(), data_); }
private:
/* Wraps our templated assign function so that we can pass them around. */
class Assign {
public:
template <size_t N>
void operator()(Data &data, int arg) const {
data[N] = arg;
}
}; // Assign
/* Wraps our templated print function so that we can pass them around. */
class Print {
public:
template <size_t N>
void operator()(const Data &data) const {
std::cout << data[N] << std::endl;
}
}; // Print
/* Our data. */
Data data_;
}; // Ints<Size>
Simple use case for the Ints class.
int main() {
Ints<5> ints;
ints.AssignAll(101);
ints.PrintAll();
}
Prints:
101
101
101
101
101