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.