Asked  7 Months ago    Answers:  5   Viewed   36 times
#include <iostream>
class Car
{
private:
  Car(){};
  int _no;
public:
  Car(int no)
  {
    _no=no;
  }
  void printNo()
  {
    std::cout<<_no<<std::endl;
  }
};
void printCarNumbers(Car *cars, int length)
{
    for(int i = 0; i<length;i++)
         std::cout<<cars[i].printNo();
}

int main()
{
  int userInput = 10;
  Car *mycars = new Car[userInput];
  for(int i =0;i < userInput;i++)
         mycars[i]=new Car[i+1];
  printCarNumbers(mycars,userInput);
  return 0;
}    

I want to create a car array but I get the following error:

cartest.cpp: In function ‘int main()’:
cartest.cpp:5: error: ‘Car::Car()’ is private
cartest.cpp:21: error: within this context

is there a way to make this initialization without making Car() constructor public?

 Answers

99

Nope.

But lo! If you use std::vector<Car>, like you should be (never ever use new[]), then you can specify exactly how elements should be constructed*.

*Well sort of. You can specify the value of which to make copies of.


Like this:

#include <iostream>
#include <vector>

class Car
{
private:
    Car(); // if you don't use it, you can just declare it to make it private
    int _no;
public:
    Car(int no) :
    _no(no)
    {
        // use an initialization list to initialize members,
        // not the constructor body to assign them
    }

    void printNo()
    {
        // use whitespace, itmakesthingseasiertoread
        std::cout << _no << std::endl;
    }
};

int main()
{
    int userInput = 10;

    // first method: userInput copies of Car(5)
    std::vector<Car> mycars(userInput, Car(5)); 

    // second method:
    std::vector<Car> mycars; // empty
    mycars.reserve(userInput); // optional: reserve the memory upfront

    for (int i = 0; i < userInput; ++i)
        mycars.push_back(Car(i)); // ith element is a copy of this

    // return 0 is implicit on main's with no return statement,
    // useful for snippets and short code samples
} 

With the additional function:

void printCarNumbers(Car *cars, int length)
{
    for(int i = 0; i < length; i++) // whitespace! :)
         std::cout << cars[i].printNo();
}

int main()
{
    // ...

    printCarNumbers(&mycars[0], mycars.size());
} 

Note printCarNumbers really should be designed differently, to accept two iterators denoting a range.

Tuesday, June 1, 2021
 
RemiX
answered 7 Months ago
85

Using the syntax that you used,

int array[100] = {-1};

says "set the first element to -1 and the rest to 0" since all omitted elements are set to 0.

In C++, to set them all to -1, you can use something like std::fill_n (from <algorithm>):

std::fill_n(array, 100, -1);

In portable C, you have to roll your own loop. There are compiler-extensions or you can depend on implementation-defined behavior as a shortcut if that's acceptable.

Tuesday, June 1, 2021
 
Sethunath
answered 7 Months ago
31

Arrays.asList can help here:

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
Sunday, June 27, 2021
 
Manju
answered 6 Months ago
26

You have to pass in something that can be deduced. The simplest thing to use is just a empty wrapper for an int: std::integral_constant. Since you only want ints I believe, we can alias it and then only accept that specific type:

template <int N>
using int_ = std::integral_constant<int, N>;

Where your C constructor just accepts that:

 template <int N>
 explicit C(int_<N> ) {
     b = new D<N>{};
 }

 C c{int_<3>{}};

You could even go all out and create a user-defined literal for this (a la Boost.Hana) so that you can write:

auto c = 3_c; // does the above

Also, consider simply forwarding the trait through to D. Metaprogramming works better if everything everywhere is a type. That is, still accept the same int_ in C:

template <class T>
explicit C(T ) {
    b = new D<T>{};
}

Where now D expects something that has a ::value:

template <class T>
struct D: public B{
    static constexpr int N = T::value;

    void foo() {
        using namespace std;
        cout << N << endl;
    }

    std::array<int, N> arr;
};

It's the same thing either way from the user of C's perspective, but just worth a thought.

Thursday, August 12, 2021
 
Ujjawal Khare
answered 4 Months ago
91

One solution is to register a TypeDescriptionProvider for the string[] type. Here is the sample code (you need to register this at the beginning of your program, before displaying any property grid):

...
TypeDescriptor.AddProvider(new StringArrayDescriptionProvider(), typeof(string[]));
...

And here is the StringArrayDescriptionProvider code:

public class StringArrayDescriptionProvider : TypeDescriptionProvider
{
    private static TypeDescriptionProvider _baseProvider;

    static StringArrayDescriptionProvider()
    {
       // get default metadata
        _baseProvider = TypeDescriptor.GetProvider(typeof(string[]));
    }

    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        // this is were we define create the instance
        // NB: .NET could do this IMHO...
        return Array.CreateInstance(typeof(string), 0);
    }

    public override IDictionary GetCache(object instance)
    {
        return _baseProvider.GetCache(instance);
    }

    public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
    {
        return _baseProvider.GetExtendedTypeDescriptor(instance);
    }

    public override string GetFullComponentName(object component)
    {
        return _baseProvider.GetFullComponentName(component);
    }

    public override Type GetReflectionType(Type objectType, object instance)
    {
        return _baseProvider.GetReflectionType(objectType, instance);
    }

    public override Type GetRuntimeType(Type reflectionType)
    {
        return _baseProvider.GetRuntimeType(reflectionType);
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return _baseProvider.GetTypeDescriptor(objectType, instance);
    }

    public override bool IsSupportedType(Type type)
    {
        return _baseProvider.IsSupportedType(type);
    }
}

This is how it will look: enter image description here

Friday, December 3, 2021
 
Luis Masuelli
answered 3 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share