Returning structure initialized from template methods in dependent base class

32 Views Asked by At

I have a method in a class template that combines some templated method calls from a dependent base class, which is also a template:

#include <iostream>

struct Struct
{
    char c;
    int i;
    double d;
};

template <typename T>
class Base
{
public:
    Base(T z): x{z} {}

    template <typename U>
    U get() { return static_cast<U>(x); }
private:
    T x;
};

template <typename T>
class Test : public Base<T>
{
public:
    using Test::Base::Base;

    Struct getS()
    {
        return Struct {
            this->get<char>(),
            this->get<int>(),
            this->get<double>(),
        };
    }
};

int main()
{
    Struct s{Test<int>(97).getS()};
    std::cout << s.c << ' ' << s.i << ' ' << s.d << std::endl;
}

I would like to get an output like a 97 97. Instead, when I compile with g++ std=c++17, I get the following errors:

snip.cpp: In member function ‘Struct Test<T>::getS()’:
snip.cpp:30:23: error: expected primary-expression before ‘{’ token
   30 |         return Struct {
      |                       ^
snip.cpp:30:22: error: expected ‘;’ before ‘{’ token
   30 |         return Struct {
      |                      ^~
      |                      ;
snip.cpp:31:23: error: expected primary-expression before ‘char’
   31 |             this->get<char>(),
      |                       ^~~~
snip.cpp:31:23: error: expected ‘;’ before ‘char’
   31 |             this->get<char>(),
      |                       ^~~~
      |                       ;

I have tried removing the Struct between return and the curly brace to get

snip.cpp: In member function ‘Struct Test<T>::getS()’:
snip.cpp:31:23: error: expected primary-expression before ‘char’
   31 |             this->get<char>(),
      |                       ^~~~
snip.cpp:31:23: error: expected ‘}’ before ‘char’
snip.cpp:30:16: note: to match this ‘{’
   30 |         return {
      |                ^
snip.cpp:31:23: error: expected ‘;’ before ‘char’
   31 |             this->get<char>(),
      |                       ^~~~
      |                       ;
snip.cpp:31:27: error: expected unqualified-id before ‘>’ token
   31 |             this->get<char>(),
      |                           ^
snip.cpp: In instantiation of ‘Struct Test<T>::getS() [with T = int]’:
snip.cpp:40:33:   required from here
snip.cpp:31:23: error: could not convert ‘{<expression error>}’ from ‘<brace-enclosed initializer list>’ to ‘Struct’
   31 |             this->get<char>(),
      |                       ^~~~
      |                       |
      |                       <brace-enclosed initializer list>

When get is not a template on U (moving the static casts to getS), this works fine. Is it possible to return an instance of Struct from Test::getS using a brace initializer, and if so, how?

FWIW, I suspect that this is related to how template parsing is done, based on this canonical answer, but I'm not sure how to fix it: https://stackoverflow.com/a/4643295/2988730.

0

There are 0 best solutions below