c++ - 编译器错误地将模板参数列表用于 < 比较

标签 c++ templates

我在样式中有一个模板函数:

template <int Exponent> DERIVED_TYPE pow(TYPE const x);

此函数作为友元函数在模板结构中内联定义:

template <ARGUMENTS>
struct unit {
    typedef unit<ARGUMENTS> type;

    ....
    template <int Exponent>
    friend constexpr unit_pow_t<type, Exponent> pow(type const x) { ... }
};

这是因为取一个带有单位的值的幂必须随着值的变化而改变单位。

当我尝试使用它时省略指数,我可以看到编译器考虑匹配的候选对象:

src/model/Tool.cpp:113:3: error: no matching function for call to 'pow'
                pow(1._m);
                ^~~
src/model/../units/Units.hpp:2266:46: note: candidate template ignored: couldn't infer template argument 'Exponent'
        friend constexpr unit_pow_t<type, Exponent> pow(type const x) {
                                                    ^
/usr/include/math.h:255:8: note: candidate function not viable: requires 2 arguments, but 1 was provided
double  pow(double, double);
        ^

到目前为止一切都如预期的那样,看到了模板,但是当然需要指定 Exponent。但是,当我这样做时,发生了意想不到的事情:

src/model/Tool.cpp:113:6: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
                pow<3>(1._m);
                ~~~^~

编译器将 pow 视为“double pow(double, double)”的地址,并将 <3 解释为比较的意图带有整数的函数指针。 clang 3.4、3.6 和 GCC 5.2 会出现此问题。

我的问题是,如何让编译器相信 <3> 是模板参数列表?

更新

我终于设法创建了一个最小的示例,对于不完整的问题感到抱歉:

template <int Exp>
struct metre {
    double value;
    template <int Exponent>
    friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
        return {0};
    }
};

int main() {
    pow<2>(metre<1>{1});
    return 0;
};

它似乎没有看到 pow:

targs.cpp:11:2: error: use of undeclared identifier 'pow'
        pow<2>(metre<1>{1});
        ^

如果我包含 cmath,我将得到与以前相同的诊断:

targs.cpp:13:5: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
        pow<2>(metre<1>{1});
        ~~~^~
1 error generated.

所以“double pow(double, double)”的存在只是掩盖了模板未被看到的问题。那么问题是,为什么编译器看不到 pow<>()?

最佳答案

friend 模板 没有必要(也没有逻辑)。使用免费功能:

template <int Exp>
struct metre {
    double value;
};

template<int B, int A>
constexpr auto pow(metre<A> const x) -> metre<A*B>
{
        return metre<A*B>{x.value};
}

int main() {
    metre<2> result = pow<2>(metre<1>{1});
    return 0;
};

Live demo on coliru .

关于c++ - 编译器错误地将模板参数列表用于 < 比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34198004/

相关文章:

没有 .cpp 文件的 C++ 类?

c++ - 使用 MFCreateSourceReaderFromByteStream 时,我必须在 Makefile 中包含什么库?

c++ - 在非成员函数上使用 delete 有什么意义?

c++为类分配内存

c++ - C/C++(还有其他语言吗?)有条件提前返回良好代码实践

c++ - 类模板中的隐藏好友模板

html - 如何在 Bootstrap 中制作这样的表格?

c++ - 为什么不能在函数中声明模板?

c++ - 如何在 gdb 中执行 `print`/evaluate c++ 模板函数

C++ 到 C 调用 : argument of type 'void (MyClass::)(u_char*,)' does not match 'void (*)(u_char*)'