Let's say, I have my List<T>
class. I have a lot of functions where I have to pass a single object of my T
type. For instance
void add(const T& item)
{
...
}
and it makes sense if T
is some class or a struct. However, if T
is a byte or integer, it's pointless or even wrong to pas it via reference, since memory pointer costs 8 bytes (4 on 32 bit system), i.e. I pass 1 byte size data type via 8 byte size pointer.
And so I decided to define argument data type using using
directive. Kind of:
using argType = const T&; requires sizeof(T) > 8
using argType = T; requires sizeof(T) <= 8
But, obviously, this code doesn't work. Can you, please, propose me other solutions for that?
CodePudding user response:
It sounds like what you need is conditional_t
:
#include <type_traits>
template<class T>
class List {
using argType = std::conditional_t<(sizeof(T) > 8), const T&, T>;
void add(argType item) { }
};
CodePudding user response:
With c 20 concepts you can add some constraints to your templates,
from en.cppreference.com/w/cpp/language/constraints
Class templates, function templates, and non-template functions (typically members of class templates) may be associated with a constraint, which specifies the requirements on template arguments, which can be used to select the most appropriate function overloads and template specializations. Named sets of such requirements are called concepts. Each concept is a predicate, evaluated at compile time, and becomes a part of the interface of a template where it is used as a constraint:
#include <string>
#include <cstddef>
#include <concepts>
// Declaration of the concept "Hashable", which is satisfied by any type 'T'
// such that for values 'a' of type 'T', the expression std::hash<T>{}(a)
// compiles and its result is convertible to std::size_t
template<typename T>
concept Hashable = requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};
struct meow {};
// Constrained C 20 function template:
template<Hashable T>
void f(T) {}
//
// Alternative ways to apply the same constraint:
// template<typename T>
// requires Hashable<T>
// void f(T) {}
//
// template<typename T>
// void f(T) requires Hashable<T> {}
int main() {
using std::operator""s;
f("abc"s); // OK, std::string satisfies Hashable
//f(meow{}); // Error: meow does not satisfy Hashable
}
In your case I think you can constraint your template as follows:
template<typename T>
concept InfTo8Bytes = requires(T a) {
sizeof (T) <= 8;
};
and use you concepts as follows:
template<InfTo8Bytes T>
class Foo {
};