7

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;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

7 Answers7

6

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.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I'd prefer `C = A` for some reason (*feels* better?), but this is a good answer. Surprised somewhat that I'm the only upvoter. – Bathsheba Oct 24 '19 at 18:51
  • @Bathsheba I changed it but I've changed it back. At first I thought having `C = A` makes the code easier to maintain because with that `B` could be removed without consequence. After thinking about that more though I realized that if `A` is removed then you need to change `B` and `C` instead of just `B`. – NathanOliver Oct 24 '19 at 18:57
4

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};
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • An interesting point. However having the same idea in my mind I would suggest another solution: the class-wrapper of int with default constructor. – Dmitry Kuzminov Oct 24 '19 at 20:47
3

You can certainly write: int a = 10, b = 10, c = 10;

Marshall Clow
  • 15,972
  • 2
  • 29
  • 45
3

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;
Dmitry Kuzminov
  • 6,180
  • 6
  • 18
  • 40
  • "By the way, defining several variables in one line is a bad practice." - says who? The MISRA guys? Some author or other? – Bathsheba Oct 24 '19 at 18:52
  • 1
    @Bathsheba One reason of why this is a bad practice is the problem in question. People forget that the initializer is applied to the last variable only. The same with pointers and references. I don't want to argue, but in many cases this is considered to be a bad practice. – Dmitry Kuzminov Oct 24 '19 at 19:00
  • I know I’m quixotic but folk shouldn’t forget. Learn the language, pretty please with sugar on top. – Bathsheba Oct 24 '19 at 19:09
  • I agree with putting declarations on seperate lines, but just saying "it is bad practice" without saying why is... well, bad practice. Why? Because blindly following rules is never good, only if you know why you can decide when it matters and when it doesnt – 463035818_is_not_an_ai Oct 24 '19 at 20:33
  • @formerlyknownas_463035818 OK, I've updated my answer. – Dmitry Kuzminov Oct 24 '19 at 20:43
  • one more nitpick "but there is no way to assign a single value "in one assignment"." but that should be "initialize" not "assign" – 463035818_is_not_an_ai Oct 24 '19 at 20:47
  • @formerlyknownas_463035818 that is why I've taken that in quotes. – Dmitry Kuzminov Oct 24 '19 at 20:48
  • the "to assign" is not in quotes, but there is no assignment, only initialization, I think it matters as you are trying to point out the difference between assignment and initialization and in `int A = 10;` there is no assignment – 463035818_is_not_an_ai Oct 24 '19 at 20:50
  • @formerlyknownas_463035818 Agree. – Dmitry Kuzminov Oct 24 '19 at 20:53
2

I recommend the universally understood and used: int a = 10, b = 10, c = 10;

That being said...


C++17 !!!

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};

C++20 !!!

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...


At last the glorious solution

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>{});
}

Burn The Witch! Burn The Witch!! Burn The Witch!!!

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!!

bolov
  • 72,283
  • 15
  • 145
  • 224
1

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

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!)

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83