首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将decltype与带有尾随返回类型语法的模板化成员函数一起使用时,存在编译错误,但不存在clang

将decltype与带有尾随返回类型语法的模板化成员函数一起使用时,存在编译错误,但不存在clang
EN

Stack Overflow用户
提问于 2017-01-18 13:01:30
回答 2查看 481关注 0票数 1

我有一个带有模板化成员函数的类,它接受一个可调用类型作为参数,并具有一个返回类型,该返回类型是使用decltype和尾随返回类型语法从所提供函数的返回类型推导而来的。下面显示了一个最小的示例。

代码语言:javascript
复制
#include <iostream>
#include <vector>

class point {
    public:
        std::vector<double> val;
        point(double in) : val({in}) {};
        template<typename T> auto eval(const T& in) -> decltype(in(val[0]));
};

template<typename T>
auto point::eval(const T& in) -> decltype(in(val[0])){
    return in(val[0]);
}

int main(int argc, char *argv[]){

    point pt(2.0);
    auto f = [](double x){return x*x;};

    std::cout << pt.val[0] << std::endl;
    std::cout << pt.eval(f) << std::endl;
}

这段代码在clang++和g++-5中可以正常编译和工作,但在g++-6中会出现以下错误。

代码语言:javascript
复制
> g++-6 main.cpp -o test -std=c++11 -Wall main.cpp:13:6: error:
> prototype for 'decltype
> (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&)' does not match any in class 'point'  auto
> point::eval(const T& in) -> decltype(in(val[0])){
>       ^~~~~ main.cpp:9:35: error: candidate is: template<class T> decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&)
>          template<typename T> auto eval(const T& in) -> decltype(in(val[0]));
>                                    ^~~~ main.cpp:9:35: error: 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>;
> decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) = double]', declared using local type 'const main(int, char**)::<lambda(double)>',
> is used but never defined [-fpermissive] main.cpp:9:35: warning:
> 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>]'
> used but never defined make: *** [all] Error 1

如果实现是内联编写的,则不会出现编译器错误。

代码语言:javascript
复制
template<typename T> auto eval(const T& in) -> decltype(in(val[0])){
            return in(val[0]);
}

此外,在c++14中使用自动返回类型推导,将签名更改为

代码语言:javascript
复制
template<typename T> auto eval(const T& in);

按照预期工作。

这是一个gcc编译器的错误,还是clang错误地接受了上面的代码?如果有的话,这些函数签名之间有什么区别?为什么内联实现会有不同之处?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-19 01:02:44

是啊,很可能是个gcc的窃听器。一个变通办法是这样做

代码语言:javascript
复制
template<typename T>
std::result_of<T(double)> point::eval(const T& in) {
票数 1
EN

Stack Overflow用户

发布于 2017-01-18 19:05:27

这是因为您没有显式实例化模板函数定义。据我所知,它不是有效的c++代码,编译器不必接受它。如果希望在其他编译器上重现此错误,请尝试将point类移到头文件中,并将point::eval定义移到.cpp文件中。因此,您要么必须为每种类型的参数使用explicitly instantiate这个定义(使用lambda是不可能的),要么(正如我建议的),除非迫切需要,否则不要使用行外模板。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41711674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档