rampion rampion - 2 months ago 11
C++ Question

"expected expression" when trying to define nested template member function

I have a templated class that has a templated member function.

Currently, I give the definition as:

template <typename... Ts>
template <size_t Column>
At<Column, Ts...> & tuple_reference<Ts...>::at(void) {
return array.at<Column>()[row];
}


But I get this error:

$ g++ example.cpp -o example -Wall -Werror -Wextra -std=c++1y -stdlib=libc++
example.cpp:42:27: error: expected expression
return array.at<Column>()[row];
^
1 error generated.


Which confounds me, as that method of
array
works fine elsewhere in my code (see
ic_arr.at<1>()
below).

Here's my full source:

#include <iostream>

// Provide a Array-of-Structs (AoS) interface to a collection that
// is actually implemented as a Struct-of-Arrays (SoA).
namespace soa {
template <typename... Ts> class tuple_array;

// index into a parameter pack to get the N'th type listed
template <int N, typename... Ts>
using At = typename std::tuple_element<N, std::tuple<Ts...>>::type;

// the "Struct" the API provides
template <typename... Ts> class tuple_reference {
private:
tuple_array<Ts...> &array;
size_t row;
public:
tuple_reference(tuple_array<Ts...> &array, size_t const &row)
: array{array}, row{row} {}
// extract the value for a given index
template <size_t Column>
At<Column, Ts...> & at(void);
};

// The toplevel interface
template <typename... Ts> class tuple_array {
private:
std::tuple<Ts *...> arrays;
size_t size{};
public:
tuple_array(Ts *... arrays, size_t const &size)
: arrays{arrays...}, size{size} {}
// extract the array for a given index
template <size_t Column> At<Column, Ts *...> &at(void) {
return std::get<Column>(arrays);
}
};

template <typename... Ts>
template <size_t Column>
At<Column, Ts...> & tuple_reference<Ts...>::at(void) {
return array.at<Column>()[row];
}
}
int main() {
int five_ints[]{0, 1, 2, 3, 4};
char six_chars[]{"abcde"};

soa::tuple_array<int, char> ic_arr{five_ints, six_chars, 5};
soa::tuple_reference<int, char> ic_ref{ic_arr, 0};

// outputs "abcde\n"
std::cout << ic_arr.at<1>() << std::endl;
// should output "0 a\n"
std::cout << ic_ref.at<0>() << " " << ic_ref.at<1>() << std::endl;
}


I'm using
Apple LLVM version 6.0 (clang-600.0.57)
.

Answer

array is a dependent name within tuple_reference.

It should be:

return array.template at<Ix>()[ix];

See here for further details.