Reputation: 89
The following expression is valid in C++:
A = B = C = 10;
The variables A, B, and C will now contain the value 10.
I'm trying to figure out how to make it so A, B, and C can contain the value of 10 when declared, not assign them later;
#include <iostream>
using namespace std;
int main()
{
int A, B, C, = 10;
int result;
result = A = B = C = 10;
cout << A << B << C << 10;
result 0;
}
Upvotes: 7
Views: 279
Reputation: 51815
If you really want to maintain your A = B = C = 10;
syntax, then you can actually do this in a single-line declaration/initializer, provided you declare B
and C
before A
. So:
int C, B, A = B = C = 10;
This is perfectly legal, and well-defined code. But I'm not saying it's what you should do. (Comments welcome giving examples of where such a form may be useful!)
Upvotes: 1
Reputation: 75668
I recommend the universally understood and used: int a = 10, b = 10, c = 10;
That being said...
We have Structured bindings so Yeey!!!
auto [a, b, c] = {10, 10, 10};
Oh, you can't do that? Oh well...
C++17
auto [a, b, c] = std::tuple{10, 10, 10};
We have Designated initializers Yeey!!
auto [a, b, c] = std::tuple{[0 ... 2] = 10};
auto [a, b, c] = (int[]){[0 ... 2] = 10};
Oh, you can't do that? Oh well...
Okey... let's do it by hand. yey? :(
auto test()
{
auto [a, b, c] = make_repeating_tuple<3, 10>();
// or, alternative
auto [a, b, c] = make_repeating_tuple<3>(10);
}
Implementation
#include <tuple>
#include <utility>
#include <type_traits>
namespace details
{
template <auto Val, std::size_t... Is>
constexpr auto make_repeating_tuple_impl(std::index_sequence<Is...>)
{
// black magic
return std::tuple{[] (auto) { return Val; }(Is)...};
}
}
template <int N, auto Val>
constexpr auto make_repeating_tuple()
{
return details::make_repeating_tuple_impl<Val>(std::make_index_sequence<N>{});
}
Implementation (alternative)
namespace details
{
template <class T, std::size_t... Is>
constexpr auto make_repeating_tuple_impl(T val, std::index_sequence<Is...>)
{
static_assert(std::is_trivially_copy_constructible_v<decltype(Val)>); // because
// black magic
return std::tuple{[=] (auto) { return val; }(Is)...};
}
}
template <int N, class T>
constexpr auto make_repeating_tuple(T val)
{
return details::make_repeating_tuple_impl(val, std::make_index_sequence<N>{});
}
auto test()
{
DECL_CHAIN_ASSIGN(10, a, b, c);
}
Implementation:
// the darkest of magics
#define DECL_CHAIN_ASSIGN(val, ...) \
auto [__VA_ARGS__] = make_repeating_tuple<PP_NARG(__VA_ARGS__)>(val)
With
#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
// taken from
// https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments
On a more serious note: Don't use the macro!!
Upvotes: 2
Reputation: 6584
Declaration differs from assignment a lot. Usually assignment operator returns the reference to the object. For example the type of this operation is int&
:
int a;
a = 10;
This allows you chaining the assignments like that: a = b = c = 10
: at the end of the day the type of this operator is int&
again and you still can add one more assignment to the right.
The definition of the variables is another story. Each variable has to get it's own value (or no value at all), but there is no way to "assign" (actually initialize) a single value "in one assignment".
However maybe this can solve your actual problem:
const int value = 10;
int a = value, b = value, c = value;
By the way, defining several variables in one line is a bad practice. Your example is one illustration of the problem. Other problems with that: what is the pointer, what is the reference and what is just a pure int in the next example?
int val;
int* a, b;
int& c = val, d = val;
Upvotes: 3
Reputation: 122133
You cannot do what you want directly. However, in my opinion wanting to initialize them with the same value is reason enough to define a class:
struct ABC {
int A,B,C;
ABC(int x) : A(x),B(x),C(x) {}
};
If there is a relation between A
,B
and C
, make it explicit. Now you can use a single value to initialize them:
ABC abc{10};
Upvotes: 4
Reputation: 180415
In C++ every variable definition has to have its own initializer. If you want to chain that then you need to use something like
int A = 10, B = A, C = B;
This will do what you want but it is required to you manually specify the initializer.
Upvotes: 6
Reputation: 595320
C++ does not work that way. Although you can declare multiple variables of the same type in a single statement, you can't initialize them with a single value, they must be initialized individually, eg
int A = 10, B = 10, C = 10;
So, what you are trying to do only works in assignments, not in declarations.
Upvotes: 1