C++ nested templates structs - c++

So i have problem with code like this:
I have struct like this
template <int N>
struct Inner
{
enum
{
val = 2*N
};
};
And i want to achive sth like this:
int v = Outer<Inner<4>>::val;
int b = Outer<false>::val;
cout<< v <<endl;
cout<< b <<endl;
My goal is to created "Outer" struct which takes bool or Inner<int N> and set Outer::val to Inner::val or bool
So i have created sth like this (not working):
template <bool B>
struct Outer
{
enum
{
val = B
};
};
template <Inner<int> I>
struct Outer
{
enum
{
val = I::val
};
};
Whats wrong with this and how to fix that?
(I have seen some similar questions, but still can't apply this to my problem)

There are some problems in your code.
First of all: you define two different Outer structs
template <bool B>
struct Outer
{ /* ... */ };
template <Inner<int> I>
struct Outer
{ /* ... */ };
And you can't.
If you want, you can declare an Outer struct and two specializations, but you have to decide what type of template argument Outer has to receive.
Because, looking at your desiderata,
int v = Outer<Inner<4>>::val;
int b = Outer<false>::val;
you want pass to it a type in one case (Inner<4>) and a value in the other case. And you can't.
You have to decide if Outer receive a type or a value. Before C++17, if receive a value, you have to decide the type of the value; starting from C++17, you can declare Outer as receiving a value of a generic type (auto as type of the value).
Problem: a value of Inner<int> can't be a template parameter (but see also the Michael Kenzel's answer, that show a possible C++20 solution based on template values arguments).
So the only solution I see (before C++20) is declare Outer as receiving a type
template <typename>
struct Outer;
Then you can define a Outer specialization for Inner types
template <int N>
struct Outer<Inner<N>>
{ enum { val = Inner<N>::val }; }; // or simply enum { val = N };
For bool values, you have to wrap they in a class; I suggest (starting from C++11) the use of the standard class std::integral_constant and the definition of the following Outer specialization
template <bool B>
struct Outer<std::integral_constant<bool, B>>
{ enum { val = B }; };
The use is as follows
int v = Outer<Inner<4>>::val;
int b = Outer<std::integral_constant<bool, false>>::val;
std::cout << v << std::endl;
std::cout << b << std::endl;
You can also use std::false_type defining b
int b = Outer<std::false_type>::val;
and, starting from C++17, also std::bool_constant (a shorthand for std::integral_constant for bool values)
int b = Outer<std::bool_constant<false>>::val;

A template parameter can be either a type, a value (non-type), or a template [temp.param]. What you're trying to achieve would require your template Outer to have a parameter that can be either a type or a value. Unfortunately, this is not possible.
What you could do is wrap your bool value in a type:
template <bool b>
struct InnerBoolean
{
static constexpr bool val = b;
};
and then have one common definition for Outer
template <typename T>
struct Outer
{
enum
{
value = T::val
};
};
and then use Outer<Inner<4>> and Outer<InnerBoolean<False>>.
Rather than write your own wrapper, if you rename val to value, you can use the wrappers that the standard library provides in std::bool_constant and std::true_type and std::false_type.
While up to C++17, a non-type template parameter cannot be of class type [temp.param]/4, C++20 will lift this restriction and allow template parameters of any literal type. Thus, as long as Inner can be a literal type, you will be able to just pass a value of type Inner directly and use an auto template parameter:
struct Inner
{
int N;
constexpr Inner(int N) : N(N) {}
constexpr operator int() const { return 2*N; }
};
template <auto val>
struct Outer
{
enum
{
value = val
};
};
auto a = Outer<Inner(4)>::value;
auto c = Outer<false>::value;

Related

Ensuring type safety without variants

Consider the following classes:
template <typename T>
class A {
public:
A(B<T> b) : b_(b) { }
T foo() {
return b_.foo();
}
private:
class B<T> b_;
}
template typename<T>
class B {
public:
T foo();
}
This nicely enforces typing across the stack (you can keep adding more layers and type them on a single type. However, I would like to have two different options on layer two:
template <typename T, typename Y>
class A {
public:
T foo() {
return b_.foo();
}
Y foo() {
return c_.foo();
}
private:
class B<T> b;
class C<Y> c;
}
template typename<T>
class B {
public:
T foo();
}
template typename<T>
class C {
public:
T foo();
}
Is there some way I could templetize the class with multiple typenames and achieve these scheme? Mind, in some situations T and Y might be the same, so there must be some more differentiations (for example B<T> vs C<Y>).
I believe I could have multiple functions foo1 and foo2 returning different values. However, I am looking for extensible solution where the customers can provide their own typenames and potentially more than two. Ideally, there would be a single overload (maybe taking identity of the internal class?)
Your idea is hard to understand, but I think you mean to take a list of template<typename> typenames and an equal number of typenames and construct the product of their zipped application?
// wrap a template<typename> typename into a normal type
// e.g. index_of_v<std::vector, std::vector> fails, but
// index_of_v<suspend<std::vector>, suspend<std::vector>> gives 0
template<template<typename> typename>
struct suspend { };
// search for X in Xs and produce a static constexpr std::size_t member values containing the index
// This is just the natural functional programming way to search a linked list
// indexOf(x, Nil) = undefined
// indexOf(x, Cons(y, xs)) = x == y ? 0 : 1 + indexOf(x, xs)
// deriving from std::integral_constant is really just noise;
// could be replaced with an explicit member definition
// but it's considered idiomatic to do this for some reason that I've forgotten
template<typename X, typename... Xs>
struct index_of { }; // base case, the default template only fires when Xs is empty, so the index is undefined
template<typename X, typename... Xs>
struct index_of<X, X, Xs...> : std::integral_constant<std::size_t, 0> { }; // if X is at the top of the list, it has index 0
template<typename X, typename Y, typename... Xs>
struct index_of<X, Y, Xs...> : std::integral_constant<std::size_t, index_of<X, Xs...>::value + 1> { }; // if it isn't, find it's index relative to the tail of the list, then shift it to be the index relative to the whole
// instead of writing index_of<X, Xs..>::value, write index_of_v<X, Xs...>
// this is a convention that you see in the standard library
template<typename X, typename... Xs>
inline constexpr std::size_t index_of_v = index_of<X, Xs...>::value;
// a class cannot have two lists of variadic template parameters
// the easiest thing to do is split the templating into two stages
// the outer template, choices, takes a list of templates as parameters
// template<typename T> class std::vector;
// int is a "base" type, so you can pass int to std::vector<int>
// but std::vector is not like int: std::vector<std::vector> is meaningless
// std::vector alone is just a template<typename> typename
// a function from types to types
template<template<typename> typename... Cs>
struct choices {
// 2nd "stage" takes the list of "normal" types
template<typename... Ts>
class type {
// apply each template to the corresponding base type
// the resulting list of base types is passed to std::tuple
// there's a "field" for each Cs<Ts> inside the tuple
std::tuple<Cs<Ts>...> parts;
public:
// hopefully self-explanatory
type(Cs<Ts>... parts) : parts(parts...) { }
// return the result of calling foo() on the container identified by C
template<template<typename> typename C>
auto foo() {
// we know the list of all the Cs,
// so just find the index of C in it and pass that to std::get
// then pass in parts to get the desired object, then call foo()
return std::get<index_of_v<suspend<C>, suspend<Cs>...>>(parts).foo();
}
};
// there's no luck for deducing Cs, since in order to *get* to types we need to specify Cs
// (choices::type is not a thing, you always write choices<Cs...>::type)
// But you can deduce `Ts`, by looking at the things contained in each container
// so, deduction guide
template<typename... Ts>
type(Cs<Ts>...) -> type<Ts...>;
};
There's nothing particularly interesting going on here. You have a list of container templates, and a list of contained types, and each object contains a tuple of objects of the desired types. Something has to be passed to foo so it knows which object to retrieve; the sanest option is the type of the container. You could also use the contained type, but apparently those aren't unique, so that wouldn't really work. You could also just pass the index directly. Since we don't know the whole type of the object, there's an auxiliary index_of type function to find the necessary index to pass to std::get. For simplicity, index_of only takes typename arguments. Since we want to search for a template<typename> typename in a list of such, all of them are wrapped in suspend to make it work.
You recover your two A types like this:
template<typename T>
struct B {
T x;
B(T x) : x(x) { }
T foo() { return x; }
};
using A1 = choices<B>;
void demonstration1() {
A1::type a(B(5)); // note the deduction guide at work
std::cout << "B: " << a.foo<B>() << "\n";
}
template<typename T>
struct C {
T x;
C(T x) : x(x) { }
T foo() { return -x; } // keeping it interesting
};
using A2 = choices<B, C>;
void demonstration2() {
A2::type a(B('a'), C(5));
std::cout << "B: " << a.foo<B>() << "; C: " << a.foo<C>() << "\n";
}
Godbolt

can C++ template detect members of specific type?

can C++ template detect members of specific type? As code below,
template <typename T>
class Element {
};
template <typename T>
class Container {
public:
Container() {
// check if T has member which type is "Element<whatever>"
// how many Element<whatever>s?
// offset?
}
};
I have a template class named Container, and I want to check:
If the passed in type T has member which type is Element<whatever>?
If so, can I get how many members which type is Element<whatever>?
If so, can I get the offset to the beginning of the class?
Explain more about requirement 3:
What I want is to access these fields(if exist) when I get a piece of data which is cast by reinterpret_cast<T>
This is doable in C++20 if the T of Container<T> is an aggregate ; I use the boost::pfr library as it simplifies this idiom but it is easily reimplementable by hand (boost::pfr's source is very simple to read)
#include <boost/pfr.hpp>
template<typename T, typename Target>
auto count_members_of_type()
{
unsigned int count = 0;
boost::pfr::for_each_field<T>(T{}, [&] <typename U> (U&&) {
count += std::is_same_v<std::remove_reference_t<U>, Target>;
});
return count;
}
given
struct Foo {
Element<int> a, b;
Element<float> c;
std::string d;
};
then
count_members_of_type<Foo, Element<int>>() == 2
Running example on gcc.godbolt.org: https://gcc.godbolt.org/z/srhn8GfWb

How to determine the outer class of a nested class structure in C++

Imagine, you have a nested class structure like the one below:
struct A
{
struct B
{
struct C{};
};
};
If you have given an instance of C, called c like
A::B::C c;
is it possible to deduce
the most outer class (here A)
the next class in hierarchy (here B)
the number of nestings (here 2)
via templates, compile-time recursion and template-specialization techniques? I've tried several templates like the following below:
template<typename Outer , typename Inner , typename Outer::Inner>
struct nested
{
typedef typename Outer::Innter type;
};
but as you can see, i am not able to do a recursion for stepwise deduction of B and C. Do you have some suggestions?
You may create a traits that you manually feed for that:
struct A
{
struct B
{
struct C{};
};
};
template <typename T> struct outter {
static constexpr const std::size_t count = 0u;
};
template <> struct outter<A::B::C>
{
using type = A::B;
static constexpr const std::size_t count = 2u;
};
template <> struct outter<A::B>
{
using type = A;
static constexpr const std::size_t count = 1u;
};
No. As far as the compiler is concerned, A, A::B and A::B::C are independent unrelated classes (except for name lookup / scope).
You might be able to do something at runtime if you know the format of your implementation's type_info::name().

How do I define / specialize a type_trait in class scope?

I have the following situation:
My problem revolves around using strongly typed enum classes as flags (just as in C# with the Flags-Attribute). I know this is not the way enum classes were meant to be used in the first place, but that it not the point of this question.
I have defined several operators and functions to use on these enum classes, and a custom type trait to distinguish normal enums from Flag-enums. Here's an example:
// Default type_trait which disables the following operators
template <typename T> struct is_flags : std::false_type {};
// Example operator to use enum class as flags
template <typename T>
std::enable_if_t<std::is_enum<T>::value && is_flags<T>::value, T&>
operator|=(T &t1, const T t2)
{
return t1 = static_cast<T>(static_cast<std::underlying_type_t<T>>(t1) |
static_cast<std::underlying_type_t<T>>(t2));
};
Now if I define any enum class i can do the following:
enum class Foo { A = 1, B = 2 };
enum class Bar { A = 1, B = 2 };
// Declare "Bar" to be useable like Flags
template <> struct is_flags<Bar> : std::true_type {};
void test()
{
Foo f;
Bar b;
f |= Foo::A; // Doesn't compile, no operator |=
b |= Bar::A; // Compiles, type_trait enables the operator
}
The above code works fine and using a macro for the template specialization it almost looks like the very convenient C# Flags-Attribute.
However, when the enum class is not defined in namespace scope, I run into an issue:
struct X
{
enum class Bar { A = 1, B = 2 };
// Following line gives: C3412: Cannot specialize template in current scope
template <> struct is_flags<Bar> : std::true_type {};
}
The type trait cannot be specialized here. I would need to define the trait outside of X, which is possible, but separates the "Flag-Attribute" from the enum declaration. It would be so nice to use this in our code since flags are used all over the place but in a rather old-fashioned manner (int + #define). All solutions to this problem I have found so far focus on classes instead of enums, where the solution is much simpler, since I can define the trait as a member of the class itself. Enums, however, cannot inherit, contain typedefs or whatever might be needed to differentiate a certain enum class from another.
So is there any possibility to define some kind of trait in a class-scope which can be used in global namespace scope to recognize special enum class-types?
EDIT: I should add that I'm using Visual Studio 2013.
UPDATE: Thanks for the answers, the tag-solution worked really well, although I had to make a subtle change (making it even more simple in the process). I'm now using this custom type trait:
template <typename T>
struct is_flags
{
private:
template <typename U> static std::true_type check(decltype(U::Flags)*);
template <typename> static std::false_type check(...);
typedef decltype(check<T>(0)) result;
public:
static const bool value = std::is_enum<T>::value && result::value;
};
Now, all I need to do is add Flags to the enum class, no matter what scope it's in:
enum class Foo { Flags, A = 0x0001, B = 0x0002 };
See also here for a similar problem and solution.
UPDATE 2: Since Visual Studio 2013 Update 2 this solution will cause compiler crashes when the is_flags trait is applied to ios-base headers. Therefore we are now using a different and cleaner approach, we use a template class which acts as the storage for an enum class and defines all operators on itself without any type-trait magic. The template class can be created implicit with the underlying enum class and explicit with the underlying type. Works a charm and is much less of an enable_if-mess.
You could tag the enumeration itself:
#include <type_traits>
template<typename T>
struct is_flags {
private:
typedef typename std::underlying_type<T>::type integral;
template<integral> struct Wrap {};
template<typename U>
static constexpr std::true_type check(Wrap<integral(U::EnumFlags)>*);
template<typename>
static constexpr std::false_type check(...);
typedef decltype(check<T>(0)) result;
public:
static constexpr bool value = std::is_enum<T>::value && result::value;
};
namespace Detail {
template <bool>
struct Evaluate;
template <>
struct Evaluate<true> {
template <typename T>
static T apply(T a, T b) { return T(); }
};
}
template <typename T>
T evalueate(T a, T b)
{
return Detail::Evaluate<is_flags<T>::value>::apply(a, b);
}
enum class E{ A = 1, B, C };
struct X {
enum class F{ EnumFlags, A = 1, B, C };
};
int main ()
{
// error: incomplete type ‘Detail::Evaluate<false>’ used in nested name specifier
// evalueate(E::A, E::B);
evalueate(X::F::A, X::F::B);
}
Here's an ugly solution using ADL instead of traits (of course you can hide the ADL inside the trait):
New operator template:
struct my_unique_enum_flag_type;
// Example operator to use enum class as flags
template <typename T>
enable_if_t<std::is_enum<T>::value
&& std::is_same<decltype(is_flags(std::declval<T>())),
my_unique_enum_flag_type>::value, T&>
operator|=(T &t1, const T t2)
{
return t1 = static_cast<T>(static_cast<underlying_type_t<T>>(t1) |
static_cast<underlying_type_t<T>>(t2));
};
Definition of is_flags for Bar:
struct X
{
enum class Bar { A = 1, B = 2 };
friend my_unique_enum_flag_type is_flags(Bar);
};
int main()
{
X::Bar a = X::Bar::A;
a |= X::Bar::B;
}
(preferably, use a more unique name than is_flags for ADL)

C++ template specialization problem

I need a C++ template that, given a type and an object of that type, it can make a decision based on whether the type is an integer or not, while being able to access the actual objects. I tried this
template <typename T, T &N>
struct C {
enum { Value = 0 };
};
template <int &N>
struct C<int, N> {
enum { Value = N };
};
but it doesn't work. Is there any way I can achieve something similar?
Edit
What I was trying to achieve was something like this, that would happen at compile time:
if (type is int) {
return IntWrapper<int_value>
else {
return type
}
You can actually pass pointers or references to objects in a template instantiation, like so:
struct X {
static const int Value = 5;
};
template <X *x>
struct C {
static const int Value = (*x).Value;
};
X x;
std::cout << C<&x>::Value << std::endl; // prints 5
but apparently all this accomplishes is to initialize the template by inferring x's type, and x also needs to be declared globally. No use for what I'm trying to do, which I think is not possible after all at compile time.
What you are attempting to do isn't valid C++ templating. You can't use arbitrary objects as template parameters, all you can use are types, integral literals and in certain specialised cases string literals.
Unless i misunderstand you, what you want is impossible. In your example you show an invalid use of a pointer template parameter.
template <X *x>
struct C {
static const int Value = (*x).Value;
};
That's not valid, since (*x).Value must be a constant expression for it to be able to initialize Value. Sure Value within class X would be fine as a constant expression when used as X::Value instead. But this time, it's not since it involves a pointer (references are equally invalid in constant expressions).
To sum up, you can't do this:
Magic<T, someT>::type
And expect ::type to be T if T isn't int, and IntWrapper<someT> otherwise, since T can only be an enumeration, integer, pointer or reference type. And in the latter two cases, you won't get at the "value" of anything pointed to by the pointer or referred to by the reference at compile time. If you are satisfied with that, it's easy to solve your problem and i'm not going to show you how (i suspect you already know how).
I think you have driven yourself into a situation where solving your problem has become impossible to do with the rules as given. Drive back some steps and show us the real problem you are trying to solve, when the matter still allows to solve things.
Perhaps a simple overloaded template method works in your case?
template<typename T>
void doSomething(const T& x)
{
// ...
}
void doSomething(int x)
{
// ...
}
Addition to the other posts: You don't need to use the enum {}-hack any more:
template<typename T, int val>
struct Test {
static const int Value = 0;
};
template <int val>
struct Test<int, val> {
static const int Value = val;
};
int main(int argc,char *argv[]) {
const int v = Test<int,1>::Value;
}
template <typename T> struct A
{
enum { Value = false };
};
template <> struct A<int>
{
enum { Value = true };
};
How about this then:
template <typename T> struct A
{
T value_;
A() : value() {}
enum { is_int = false };
};
template <> struct A<int>
{
int value_;
explicit A( int v ) : value_( v ) {}
enum { is_int = true };
};
I need a C++ template that, given a
type and an object of that type, it
can make a decision based on whether
the type is an integer or not, while
being able to access the actual
objects.
You can make decisions based on the type being an integer or not, the problem is it's impossible to declare a template with an object of any type. So the question on how to decide wether a type is an integer is moot.
Note that in all answers your original template is neatly changed to
template < typename T, int >
class C {};
instead of your
template< typename T, T >
class C {};
But while C<int, 5> is a perfectly valid declaration, this is not the case for an arbitrary type T, case in point C<float, 5.> will give a compiler error.
Can you post what you're trying to achieve exactly?
And for the record, if the second template argument is always an int, and you simply want to take its value if the type is an integer type, and 0 otherwhise, you can simply do:
#include <limits>
template< typename T, int N >
class C {
static const int Value = (std::numeric_limits<T>::is_integer) ? N : 0;
};
You can do it like this:
template<typename T, int val>
struct Test
{
enum {Value = 0};
};
template <int val>
struct Test<int, val>
{
enum {Value = val};
};
int main(int argc,char *argv[])
{
int v = Test<int,1>::Value;
}
simple fix to your code - loose the reference:
template <typename T, T N>
struct C {
enum { Value = 0 };
};
template <int N>
struct C<int, N> {
enum { Value = N };
};
using reference in a template argument is meaningless anyway because you're not actually passing the argument anywhere.
Check out Alexandrescu's Modern C++ Design. I believe chapter 2 has a correct example of what you want to do.
Template specialization can be achieved like this (code taken from www.cplusplus.com):
// template specialization
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase () {return ++element;}
};
// class template specialization:
template <>
class mycontainer <char> {
char element;
public:
mycontainer (char arg) {element=arg;}
char uppercase ()
{
if ((element>='a')&&(element<='z'))
element+='A'-'a';
return element;
}
};
int main () {
mycontainer<int> myint (7);
mycontainer<char> mychar ('j');
cout << myint.increase() << endl;
cout << mychar.uppercase() << endl;
return 0;
}
In your case you would have to replace the char by what you want in the class template specialization. Now, I am not really sure what you are trying to accomplish but I hope the example above is a good indicator to how you can do some template specialization.
What I was trying to achieve was something like this, that would happen at compile time:
if (type is int) {
return IntWrapper<int_value>
else {
return type
}
I'm not sure why you aren't using IntWrapper to begin with. Where does the need come from to wrap a compile-time integer constant into an IntWrapper, if it is int?
Otherwise it looks a bit that you are trying to instantiate templates with data that is only available at run-time.