I have a template class called Basis
, instantiated like this:
Basis<std::function<sla::col<3>(const sla::col<2>&)>> basis;
and defined like this:
template<typename V>
struct Basis {
std::vector<V> vectors;
Basis()
{}
explicit Basis(std::vector<V>&& vectors)
: vectors(vectors)
{}
// if V+=V and V*=double are defined *** THE FOLLOWING LINE GENERATES THE COMPILER ERROR ***
template<typename T = std::remove_reference_t<decltype(std::declval<V&>() += (std::declval<V&>() *= double()))>>
V operator*(const std::vector<double>& coeffs) const {
V result = zero<V>();
if (coeffs.size() > vectors.size()) {
throw std::runtime_error("coeffs count exceeds basis vectors count");
}
for (size_t k = 0; k < coeffs.size(); k++) {
V term = vectors[k];
term *= coeffs[k];
result += term;
}
return result;
}
// alternative to operator* if V does not define += and *=
LinearCombination<V> linearCombination(const std::vector<double>& coeffs) const {
LinearCombination<V> result;
if (coeffs.size() > vectors.size()) {
throw std::runtime_error("coeffs count exceeds basis vectors count");
}
for (size_t k = 0; k < coeffs.size(); k++) {
result += typename LinearCombination<V>::Term{ coeffs[k], vectors[k] };
}
return result;
}
// if V(x) is defined
template<typename X>
auto operator()(X x) const -> Basis<std::remove_reference_t<decltype(std::declval<V>()(x))>> {
return Basis<std::remove_reference_t<decltype(std::declval<V>()(x))>>(util::transformation(vectors, [x](const V& v) {
return v(x);
}));
}
// if V[i] is defined
template<typename I>
auto operator[](I i) const -> Basis<std::remove_reference_t<decltype(std::declval<V>()[i])>> {
return Basis<std::remove_reference_t<decltype(std::declval<V>()[i])>>(util::transformation(vectors, [i](const V& v) {
return v[i];
}));
}
}
It compiles fine with MSVC, but when compiling with GCC I get the following error:
In instantiation of ‘struct Basis<std::function<sla::col<3>(const sla::col<2>&)> >’:
[LINE_NUMBER_OF_INSTANTIATION]: required from here
[LINE_NUMBER_OF_DECLARATION_OF_OPERATOR*=]: error: no match for ‘operator*=’ (operand types are ‘std::function<sla::col<3>(const sla::col<2>&)>’ and ‘double’)
template<typename T = std::remove_reference_t<decltype(std::declval<V&>() += (std::declval<V&>() *= double()))>>
Why would GCC be instantiating Basis<std::function<sla::col<3>(const sla::col<2>&)>>::operator*
given that std::function<sla::col<3>(const sla::col<2>&)>::operator*=
is not defined?
Does the error message imply that GCC thinks basis.operator*()
is being invoked somewhere?
I could only find references to members basis.operator()()
, basis.linearCombination()
. But when I isolate code with only those references, the problem disappears. For this reason I have been unable to isolate a minimal complete example to reproduce the problem for this question, as I have no idea where the problem is actually coming from.
I'm just hoping for any pointers that could lead me in the right direction, on what might be causing the problem.