3

Templated constructor is not accessible in struct. I would like to allow for non-templated construction still, if possible. If its not possible I would like to understand what wall this actually is in the language, if any..

The error is this: Expected '(' for function-style cast or type construction

It's a syntax error. How you construct with a template is name(args), and that is exactly what:

A a = A<short>(1); ... is doing, right?

#include <iostream>

struct A {
    int i;
    A() : i(0) { }
    
    template <typename T>
    A(T i) : i(int(i)) { }

    void print() {
         std::cout << i << std::endl;
    }
};

int main() {
    A a = A<short>(1);
    a.print();
    return 0;
}

-- EDIT --

Adding the #1 problem I ran into at first. The answer came quick but theres a bit more nuance here. Let me describe it better.

struct A {
    std::function<int(int)> fn;

    template <typename T>
    A() {
        fn = [](int i) {
            /// merely using T somewhere in this lambda
            return int(T(i));
        };
    }
};

int main(int c, const char *v[]) {
    A a = A<int>();
}

I originally stated it must have the default constructor but I wasn't actually needing it that way. I am, however not directly referencing the template param in any argument and I know why that must be what I'm stuck with?

-- EDIT 3 --

I simply needed a class-mode template setup in my case. The reason I was a bit stubborn was the need to keep a bit of code out of the header.

Kalen
  • 3,106
  • 8
  • 29
  • 42
  • Does this answer your question? [C++ template constructor](https://stackoverflow.com/questions/3960849/c-template-constructor) – Klaus Dec 23 '21 at 09:01
  • You have to add some parameters to make it possible to perform type deduction; or make `A` template from the beginning. – songyuanyao Dec 23 '21 at 09:50

2 Answers2

5

The templated constructor will be selected if you construct A from a short explictly

#include <iostream>

struct A 
{
    int i;
    A() : i(0) { }

    // i(int(i)) { } <== do NOT use "C" style casts in C++
    template <typename T>
    A(T v) :
        i{ static_cast<int>(v) } 
    {
        std::cout << "using templated constructor\n";
    }


    void print() {
        std::cout << i << std::endl;
    }
};

int main() 
{
    A a{ short{1} }; // construct a from a short
    a.print();
    return 0;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
2

A is a non-template class, so you can't specify template argument for it like A<short>. And there's no way to specify template argument for constructor template; template argument could only be deduced from constructor argument.

So you can

A a = A(1); // T will be deduced as int
            // if pass a short like static_cast<short>(1) T will be deduced as short

Or just

A a(1); // T will be deduced as int
        // if pass a short like static_cast<short>(1) T will be deduced as short
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Looks like I may have to edit this one. I'm doing a bit more in my use-case than I described. – Kalen Dec 23 '21 at 08:45
  • 1
    No but by explicitly constructing a from a short the templated constructor will be selected – Pepijn Kramer Dec 23 '21 at 08:49
  • Well my problem is I am trying to do this with an app class constructor, with a View type given as a template param. In this case, it's passed by requirement with a lambda being created with its use. Still, I cannot pass the – Kalen Dec 23 '21 at 09:10
  • @Kalen Is there any implicit conversion required? From lambda to type. Implicit conversion won't be considered in template argument deduction, so you have to perform the conversion explicitly before pass to the constructor. – songyuanyao Dec 23 '21 at 09:15