0

AFAIK a template class or function can take default template arguments so I have this example for practice sake I am simulating an adapter class Array:

template<typename T = int, unsigned sz = 5>
class Array
{
public:
    Array(T const& = T());
    void push_back(T const&);
    void pop_back();
    T& front();
    T& back();
    typename std::vector<T>::iterator begin();
    typename std::vector<T>::iterator end();

private:
    //std::vector<T> arr_(sz, T()){}; // error: sz is not a type
    std::vector<T> arr_{sz, T()};
};

template <typename T, unsigned sz>
Array<T, sz>::Array(T const& val) :
    arr_(sz, val)
{}

template <typename T, unsigned sz>
void Array<T, sz>::push_back(T const& x)
{
    arr_.push_back(x);
}

template <typename T, unsigned sz>
void Array<T, sz>::pop_back()
{
    arr_.pop_back();
}

template <typename T, unsigned sz>
T& Array<T, sz>::front()
{
    return arr_.at(0);
}

template <typename T, unsigned sz>
T& Array<T, sz>::back()
{
    return arr_.at(sz - 1);
}

template <typename T, unsigned sz>
typename std::vector<T>::iterator Array<T, sz>::begin()
{
    return arr_.begin();
}

template <typename T, unsigned sz>
typename std::vector<T>::iterator Array<T, sz>::end()
{
    return arr_.end();
}

int main()
{

    Array<> ar_d(3.14);
    for(auto const& e : ar_d)
        std::cout << e << ", ";
    std::cout << '\n';

    //Array<char*> ar("Hi there!");// works
    //Array<char*, 10> ar("Hi there!"); // works
    Array<> ar("Hi there!"); // why this doesn't work? : invalid conversion from const char* to int


    std::cout << "\ndone!\n";
}
  • Why I can't declare the member arr_ that why std::vector<T> arr_(sz, T()){}; but using std::vector<T> arr_{sz, T()}; works? is the first wrong because of some vexing-parse errors?

  • As you can see I class template Array has defaults for all of its template arguments and a default value for the constructor so why I can't write this: Array<> ar("Hi there!");?

Because as I guess arr_ is initialized from the default value of sz_ which is 5 and the constructor deduces the type of "Hi there!" as const char* so in other words arr_ is a vector of 5 const char* ("Hi there!", "Hi there!"...) But I get the error: cannot convert from const char* to int.

The error:

In function ‘int main()’: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]| note: initializing argument 1 of ‘Array<T, sz>::Array(const T&) [with T = int; unsigned int sz = 5]’

In the remaining initializations in main are correct.

Thank you!

Maestro
  • 2,512
  • 9
  • 24
  • 1
    please one question per question. For the "hi there" case, please include the complete compiler error in the question – 463035818_is_not_an_ai Nov 05 '20 at 12:15
  • you made `int` default for `T`, so why should `T` not be `int` ? – 463035818_is_not_an_ai Nov 05 '20 at 12:17
  • @idclev463035818: Yes but why the compiler cannot deduce `const char*` rather than uses the default type `int`? – Maestro Nov 05 '20 at 12:19
  • 2
    This is called "the most vexing parse", and is a well-known parsing quirk in the complex C++ grammar. When parenthesis are used the whole thing looks like a class method declaration, and it fails to parse. See the linked question for more information. – Sam Varshavchik Nov 05 '20 at 12:20
  • Thank you @SamVarshavchik. But I am passing `sz` as a value so the compiler should know that it is not a function declaration? – Maestro Nov 05 '20 at 12:22
  • 2
    It's too late. By the time the compiler sees the `(`, it already looks like a function declaration, and then continues to get parsed as one. `(` indicates that this should be a function declaration, but it fails to parse as one. Just because it fails to parse as a proper function declaration the compiler is not going to attempt to re-parse it as a method declaration with an initializer. C++ does not work this way. – Sam Varshavchik Nov 05 '20 at 12:27
  • @SamVarshavchik: OK thanks. finally what about the error here `Array<> ar("Hi there!");`? Why the compiler doesn't deduce `const char*` as template argument for `T` ? – Maestro Nov 05 '20 at 12:43
  • 1
    Which part of "the `(` indicates that this needs to be parsed as a function/method call/declaration" is unclear to you? Nothing can be deduced for any template unless the whole thing gets parsed as a template or an object declaration with initialization. And it doesn't even get to that point. – Sam Varshavchik Nov 05 '20 at 12:50
  • 1
    Also note that when you said `Array` and `Array` worked, you'd still have a problem with template inference. If you write `Array ar("Hi there!")`, it will recognize that as a variable declaration and infer `T = char[10], sz = 5U`. But a `char[10]` isn't actually the same thing as a `char*`, and in particular it means that the initialization that uses `T()` to populate `arr_` will fail. – Nathan Pierson Nov 05 '20 at 15:21
  • @NathanPierson: Thank you that makes sense bro. – Maestro Nov 05 '20 at 19:38

0 Answers0