GCC实例化了一种应该彻底解决的方法?

时间:2020-06-14 01:13:06

标签: c++ gcc compiler-errors c++14 sfinae

我有一个名为Basis的模板类,它的实例化如下:

Basis<std::function<sla::col<3>(const sla::col<2>&)>> basis;

并定义如下:

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];
        }));
    }
}

使用MSVC可以正常编译,但是使用GCC编译时会出现以下错误:


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()))>>

鉴于Basis<std::function<sla::col<3>(const sla::col<2>&)>>::operator*未定义,为什么GCC会实例化std::function<sla::col<3>(const sla::col<2>&)>::operator*=

错误消息是否暗示GCC认为basis.operator*()正在某个地方被调用?

我只能找到对成员basis.operator()()basis.linearCombination()的引用。但是,当我仅使用那些引用隔离代码时,问题就消失了。因此,由于无法确定问题的实际来源,因此我无法给出一个完整的例子来重现该问题。

我只是希望能找到可能导致问题发生的正确方向的任何指针。

0 个答案:

没有答案