The variadic template constructor of my class cannot modify my class members, why is that so? ...
Writing Thesis: Copying from published papers
Are my PIs rude or am I just being too sensitive?
How can you insert a "times/divide" symbol similar to the "plus/minus" (±) one?
Passing functions in C++
How do I keep my slimes from escaping their pens?
Why use gamma over alpha radiation?
Unexpected result with right shift after bitwise negation
How should I respond to a player wanting to catch a sword between their hands?
Can I throw a longsword at someone?
Is dark matter really a meaningful hypothesis?
Area of a 2D convex hull
How is simplicity better than precision and clarity in prose?
Is it possible to ask for a hotel room without minibar/extra services?
What computer would be fastest for Mathematica Home Edition?
How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time
Blender game recording at the wrong time
AWS IAM: Restrict Console Access to only One Instance
When is phishing education going too far?
3 doors, three guards, one stone
How does modal jazz use chord progressions?
What can I do if my MacBook isn’t charging but already ran out?
Sorting inherited template fields
Cauchy Sequence Characterized only By Directly Neighbouring Sequence Members
What do I do if technical issues prevent me from filing my return on time?
The variadic template constructor of my class cannot modify my class members, why is that so?
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)
The Ask Question Wizard is Live!
Data science time! April 2019 and salary with experienceWhy can templates only be implemented in the header file?Where and why do I have to put the “template” and “typename” keywords?Variadic Template TemplateClass Headers and using constructors in my class .cpp file: “error: class 'Test' does not have any field named 'counter'”C++ confused between cast operator and variadic constructorIs it possible to create a completely arbitrary private member tuple in a C++11 variadic class constructor?How to solve this with variadic templatesVariadic Typenames in Template Functionsmetaprogramming with variadic templates in C++Template variadic argument referenced from another argument
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.
What I have tried:
using pointer
int* count
instead ofint count
using a setter to set the
counter
I have already googled around for hours, but cannot find a solving answer.
Header file "test.h":
#include <cstdarg>
#include <iostream>
class Counter {
private:
int count = 0;
int tmp;
public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};
main.cpp:
#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}
The output I got:
start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...
c++ c++11 recursion variadic-templates
New contributor
add a comment |
I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.
What I have tried:
using pointer
int* count
instead ofint count
using a setter to set the
counter
I have already googled around for hours, but cannot find a solving answer.
Header file "test.h":
#include <cstdarg>
#include <iostream>
class Counter {
private:
int count = 0;
int tmp;
public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};
main.cpp:
#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}
The output I got:
start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...
c++ c++11 recursion variadic-templates
New contributor
Perhaps the intention here is forcount
to bestatic
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to printtmp
.
– Jonathan Mee
yesterday
add a comment |
I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.
What I have tried:
using pointer
int* count
instead ofint count
using a setter to set the
counter
I have already googled around for hours, but cannot find a solving answer.
Header file "test.h":
#include <cstdarg>
#include <iostream>
class Counter {
private:
int count = 0;
int tmp;
public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};
main.cpp:
#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}
The output I got:
start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...
c++ c++11 recursion variadic-templates
New contributor
I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.
What I have tried:
using pointer
int* count
instead ofint count
using a setter to set the
counter
I have already googled around for hours, but cannot find a solving answer.
Header file "test.h":
#include <cstdarg>
#include <iostream>
class Counter {
private:
int count = 0;
int tmp;
public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};
main.cpp:
#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}
The output I got:
start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...
c++ c++11 recursion variadic-templates
c++ c++11 recursion variadic-templates
New contributor
New contributor
edited yesterday
TrebledJ
3,90421431
3,90421431
New contributor
asked yesterday
PrettyCoffeePrettyCoffee
814
814
New contributor
New contributor
Perhaps the intention here is forcount
to bestatic
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to printtmp
.
– Jonathan Mee
yesterday
add a comment |
Perhaps the intention here is forcount
to bestatic
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to printtmp
.
– Jonathan Mee
yesterday
Perhaps the intention here is for
count
to be static
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp
.– Jonathan Mee
yesterday
Perhaps the intention here is for
count
to be static
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp
.– Jonathan Mee
yesterday
add a comment |
2 Answers
2
active
oldest
votes
Counter(rest ...);
creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count
therefore you get stream of 1 1 1 1
If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:
template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
add a comment |
As explained by VTT, calling Counter()
inside the body of the constructor create a new Counter()
object.
You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.
I also would advise you against initialization (and modifications) of member object inside the body of contructors.
If your target is initialize count
with the number of the arguments and tmp
with the value of the last argument, I propose the following ("tag dispatching" based) solution
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "n"; }
};
You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest...
to a method (maybe static
and also constexpr
, if you want) used to initialize tmp
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "n"; }
};
Off Topic: to be precise, your Counter
class isn't "a variadic template class".
It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).
-- EDIT --
The OP asks
What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
A static const (maybe also constexpr
) make sense only if the counter is a common value between all the instances of the class.
At the moment doesn't make sense because your Counter
accept initialization lists of different length.
But suppose that number of the argument of the constructor is a template parameter (say N
)... in that case count
is simply N
and can be static constexpr
. You can define a std::array<int, N>
for the values (also a int[N]
but I suggest to avoid to use C-style arrays, when possible, and use std::array
instead) and, making the constructor constexpr
, you can impose the compile time initialization.
The following is a full compiling C++14 example (uses std::make_index_sequence
and std::index_sequence
that, unfortunately, are available only starting from C++14).
Observe that I've defined the f8
variable in main()
as constexpr
: only this way you can impose (pretending there isn't the as-is rule) that f8
is initialized compile-time
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
If you can use a C++17 enabled compiler, you can also use a deduction guide for foo
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
so there is no needs to explicate the template argument defining f8
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
because it's deduced from the number of the argument of the constructor.
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that astatic
variable is a variable common to all instances of the class, so astatic
count
variable (constant, moreover) make sense only if thecount
value is common to all instances ofCounter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55665792%2fthe-variadic-template-constructor-of-my-class-cannot-modify-my-class-members-wh%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Counter(rest ...);
creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count
therefore you get stream of 1 1 1 1
If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:
template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
add a comment |
Counter(rest ...);
creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count
therefore you get stream of 1 1 1 1
If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:
template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
add a comment |
Counter(rest ...);
creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count
therefore you get stream of 1 1 1 1
If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:
template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter(rest ...);
creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count
therefore you get stream of 1 1 1 1
If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:
template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
edited yesterday
answered yesterday
VTTVTT
26.3k42550
26.3k42550
add a comment |
add a comment |
As explained by VTT, calling Counter()
inside the body of the constructor create a new Counter()
object.
You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.
I also would advise you against initialization (and modifications) of member object inside the body of contructors.
If your target is initialize count
with the number of the arguments and tmp
with the value of the last argument, I propose the following ("tag dispatching" based) solution
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "n"; }
};
You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest...
to a method (maybe static
and also constexpr
, if you want) used to initialize tmp
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "n"; }
};
Off Topic: to be precise, your Counter
class isn't "a variadic template class".
It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).
-- EDIT --
The OP asks
What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
A static const (maybe also constexpr
) make sense only if the counter is a common value between all the instances of the class.
At the moment doesn't make sense because your Counter
accept initialization lists of different length.
But suppose that number of the argument of the constructor is a template parameter (say N
)... in that case count
is simply N
and can be static constexpr
. You can define a std::array<int, N>
for the values (also a int[N]
but I suggest to avoid to use C-style arrays, when possible, and use std::array
instead) and, making the constructor constexpr
, you can impose the compile time initialization.
The following is a full compiling C++14 example (uses std::make_index_sequence
and std::index_sequence
that, unfortunately, are available only starting from C++14).
Observe that I've defined the f8
variable in main()
as constexpr
: only this way you can impose (pretending there isn't the as-is rule) that f8
is initialized compile-time
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
If you can use a C++17 enabled compiler, you can also use a deduction guide for foo
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
so there is no needs to explicate the template argument defining f8
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
because it's deduced from the number of the argument of the constructor.
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that astatic
variable is a variable common to all instances of the class, so astatic
count
variable (constant, moreover) make sense only if thecount
value is common to all instances ofCounter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
add a comment |
As explained by VTT, calling Counter()
inside the body of the constructor create a new Counter()
object.
You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.
I also would advise you against initialization (and modifications) of member object inside the body of contructors.
If your target is initialize count
with the number of the arguments and tmp
with the value of the last argument, I propose the following ("tag dispatching" based) solution
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "n"; }
};
You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest...
to a method (maybe static
and also constexpr
, if you want) used to initialize tmp
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "n"; }
};
Off Topic: to be precise, your Counter
class isn't "a variadic template class".
It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).
-- EDIT --
The OP asks
What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
A static const (maybe also constexpr
) make sense only if the counter is a common value between all the instances of the class.
At the moment doesn't make sense because your Counter
accept initialization lists of different length.
But suppose that number of the argument of the constructor is a template parameter (say N
)... in that case count
is simply N
and can be static constexpr
. You can define a std::array<int, N>
for the values (also a int[N]
but I suggest to avoid to use C-style arrays, when possible, and use std::array
instead) and, making the constructor constexpr
, you can impose the compile time initialization.
The following is a full compiling C++14 example (uses std::make_index_sequence
and std::index_sequence
that, unfortunately, are available only starting from C++14).
Observe that I've defined the f8
variable in main()
as constexpr
: only this way you can impose (pretending there isn't the as-is rule) that f8
is initialized compile-time
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
If you can use a C++17 enabled compiler, you can also use a deduction guide for foo
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
so there is no needs to explicate the template argument defining f8
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
because it's deduced from the number of the argument of the constructor.
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that astatic
variable is a variable common to all instances of the class, so astatic
count
variable (constant, moreover) make sense only if thecount
value is common to all instances ofCounter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
add a comment |
As explained by VTT, calling Counter()
inside the body of the constructor create a new Counter()
object.
You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.
I also would advise you against initialization (and modifications) of member object inside the body of contructors.
If your target is initialize count
with the number of the arguments and tmp
with the value of the last argument, I propose the following ("tag dispatching" based) solution
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "n"; }
};
You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest...
to a method (maybe static
and also constexpr
, if you want) used to initialize tmp
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "n"; }
};
Off Topic: to be precise, your Counter
class isn't "a variadic template class".
It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).
-- EDIT --
The OP asks
What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
A static const (maybe also constexpr
) make sense only if the counter is a common value between all the instances of the class.
At the moment doesn't make sense because your Counter
accept initialization lists of different length.
But suppose that number of the argument of the constructor is a template parameter (say N
)... in that case count
is simply N
and can be static constexpr
. You can define a std::array<int, N>
for the values (also a int[N]
but I suggest to avoid to use C-style arrays, when possible, and use std::array
instead) and, making the constructor constexpr
, you can impose the compile time initialization.
The following is a full compiling C++14 example (uses std::make_index_sequence
and std::index_sequence
that, unfortunately, are available only starting from C++14).
Observe that I've defined the f8
variable in main()
as constexpr
: only this way you can impose (pretending there isn't the as-is rule) that f8
is initialized compile-time
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
If you can use a C++17 enabled compiler, you can also use a deduction guide for foo
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
so there is no needs to explicate the template argument defining f8
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
because it's deduced from the number of the argument of the constructor.
As explained by VTT, calling Counter()
inside the body of the constructor create a new Counter()
object.
You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.
I also would advise you against initialization (and modifications) of member object inside the body of contructors.
If your target is initialize count
with the number of the arguments and tmp
with the value of the last argument, I propose the following ("tag dispatching" based) solution
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "n"; }
};
You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest...
to a method (maybe static
and also constexpr
, if you want) used to initialize tmp
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "n"; }
};
Off Topic: to be precise, your Counter
class isn't "a variadic template class".
It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).
-- EDIT --
The OP asks
What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
A static const (maybe also constexpr
) make sense only if the counter is a common value between all the instances of the class.
At the moment doesn't make sense because your Counter
accept initialization lists of different length.
But suppose that number of the argument of the constructor is a template parameter (say N
)... in that case count
is simply N
and can be static constexpr
. You can define a std::array<int, N>
for the values (also a int[N]
but I suggest to avoid to use C-style arrays, when possible, and use std::array
instead) and, making the constructor constexpr
, you can impose the compile time initialization.
The following is a full compiling C++14 example (uses std::make_index_sequence
and std::index_sequence
that, unfortunately, are available only starting from C++14).
Observe that I've defined the f8
variable in main()
as constexpr
: only this way you can impose (pretending there isn't the as-is rule) that f8
is initialized compile-time
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
If you can use a C++17 enabled compiler, you can also use a deduction guide for foo
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
so there is no needs to explicate the template argument defining f8
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
because it's deduced from the number of the argument of the constructor.
edited yesterday
answered yesterday
max66max66
39.4k74575
39.4k74575
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that astatic
variable is a variable common to all instances of the class, so astatic
count
variable (constant, moreover) make sense only if thecount
value is common to all instances ofCounter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
add a comment |
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that astatic
variable is a variable common to all instances of the class, so astatic
count
variable (constant, moreover) make sense only if thecount
value is common to all instances ofCounter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?
– PrettyCoffee
yesterday
@PrettyCoffee - Let me think... Take in count that a
static
variable is a variable common to all instances of the class, so a static
count
variable (constant, moreover) make sense only if the count
value is common to all instances of Counter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.– max66
yesterday
@PrettyCoffee - Let me think... Take in count that a
static
variable is a variable common to all instances of the class, so a static
count
variable (constant, moreover) make sense only if the count
value is common to all instances of Counter
. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
@PrettyCoffee - answer improved; hope this helps.
– max66
yesterday
add a comment |
PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55665792%2fthe-variadic-template-constructor-of-my-class-cannot-modify-my-class-members-wh%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Perhaps the intention here is for
count
to bestatic
, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to printtmp
.– Jonathan Mee
yesterday