Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clang不会注意到默认的模板参数 背景 根据C++标准,当用默认模板参数向前声明模板类型时,它们都只能出现在一个声明中。例如: //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //坏例子 模板 类示例;//远期申报 模板//错误:模板参数重新定义默认参数 类示例{};//定义 问题_C++_Templates_Clang_Default Arguments - Fatal编程技术网

Clang不会注意到默认的模板参数 背景 根据C++标准,当用默认模板参数向前声明模板类型时,它们都只能出现在一个声明中。例如: //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //坏例子 模板 类示例;//远期申报 模板//错误:模板参数重新定义默认参数 类示例{};//定义 问题

Clang不会注意到默认的模板参数 背景 根据C++标准,当用默认模板参数向前声明模板类型时,它们都只能出现在一个声明中。例如: //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //很好的例子 模板 类示例;//远期申报 模板 类示例{};//定义 //坏例子 模板 类示例;//远期申报 模板//错误:模板参数重新定义默认参数 类示例{};//定义 问题,c++,templates,clang,default-arguments,C++,Templates,Clang,Default Arguments,在我的代码中,我在不同的文件中有很多转发声明,因此在定义中放置默认参数是有意义的: //foo.hpp、bar.hpp、baz.hpp等。 模板 课堂示范; //example.hpp 模板 类示例{}; 而且,正如预期的那样,它在任何地方都运行良好。。。除了叮当声!我把问题缩小到这一点: 在clang中,如果类模板具有默认参数,但未在该类的第一个正向声明中声明这些参数,并且在声明该类的实例时未指定尖括号,则clang将忽略默认参数,并引发错误“没有可行的构造函数或用于推断模板参数的推断指南

在我的代码中,我在不同的文件中有很多转发声明,因此在定义中放置默认参数是有意义的:

//foo.hpp、bar.hpp、baz.hpp等。
模板
课堂示范;
//example.hpp
模板
类示例{};
而且,正如预期的那样,它在任何地方都运行良好。。。除了叮当声!我把问题缩小到这一点:
在clang中,如果类模板具有默认参数,但未在该类的第一个正向声明中声明这些参数,并且在声明该类的实例时未指定尖括号,则clang将忽略默认参数,并引发错误“没有可行的构造函数或用于推断模板参数的推断指南…”

例子
//很好的例子
模板
课堂示范;
模板
类示例{};
int main(){
示例e;//错误:对于“Example”的模板参数的推导,没有可行的构造函数或推导指南
}
  • =void
    移动到转发声明可以解决问题,但对我来说不可行,因为我的转发声明位于不同的文件中,我不知道哪一个将首先出现。(由于我的默认值位于代码库深处的某个模糊文件中,因此问题也非常严重)
  • 更改
    示例e
    示例e
    解决了这个问题,但对我来说不可行,因为我是一名库开发人员,不希望所有用户在我的课后键入
  • 添加一个向前声明文件
    example_fwd.hpp
    ,其中包含一个向前声明,而不是每次向前声明,可以解决问题,但如果有更好的解决方案,我希望避免这种情况
问题: 在这种情况下谁是对的:clang还是其他编译器?这是一个编译器错误吗?我怎样才能避免这个问题(除了我上面描述的部分解决方案)? 我已经找到了(以及相关的stackoverflow问题),但这是关于模板参数的,并且在一年前被标记为已修复

编辑
这看起来像一个bug,现在在LLVM bugtracker()上有报道。

我不知道谁是对的,但是

我怎样才能避免这个问题(除了我上面描述的部分解决方案)

添加以下扣除规则怎么样

Example() -> Example<>;
Example()->Example;
下面的代码(显然是C++17)同时使用g++和clang进行编译++

template <class T>
class Example;

template <class T = void>
class Example {};

Example() -> Example<>;

int main() {
    Example e;
}
模板
课堂示范;
模板
类示例{};
示例()->示例;
int main(){
示例e;
}

该标准不区分默认模板参数是在模板的定义中定义的,还是在模板的声明中定义的

因为Clang在默认参数出现在声明中而不是定义中时接受代码,所以这两种行为中至少有一种是错误的。考虑到

模板参数是C的模板参数,后跟构造函数的模板参数(包括默认模板参数)(如果有)

,我想说Clang应该使用默认的模板参数

我认为您可以通过遵循一种常见做法来避免此错误:

  • 如果必须转发声明,请为此转发声明创建专用头文件

  • 在此转发声明文件中定义默认参数

  • 还应在提供模板定义的头文件中包含此文件


  • 例如,请参见考虑以下因素的iosfwd

    -可用的默认模板参数集是通过将模板所有先前声明中的默认参数以与默认函数参数相同的方式合并而获得的[ 例如:


    这将有效地允许执行
    示例e

    应接受原始代码。作为一种变通方法,您可以提供一个使用默认参数的演绎指南,该方法已在中提出

    Example() -> Example<>;
    
    Example()->Example;
    
    扣分指南是否能解决此问题?似乎……不确定是否适合此错误报告。LLVM支持可能更适合此情况。@SergeyA但这是确认这是一个错误的完美地方,特别是因为OP不确定。我不确定谁在这里介绍了扣分指南,但在clang中得分我接受这一点,而不是因为你是第一个解释为什么这是一个bug的人。对于更一般的情况,可以改进演绎指南:
    模板示例(Args&&…->Example
    ,以接受任意数量的任何类型的参数。看起来我正在提交bug报告。“这将有效地允许执行
    示例e
    。“-但是NatanOliver指出的那一部分呢?@max66 NatanOliver指出的那一部分不涉及启用CTAD的说明符。指针类型不包括在内。@max66另外,请注意,以前版本的clang甚至不接受
    示例e
    ,但后来发生了变化。
    template<class T1 = int, class T2 = int> class A;
    
    template <class T>
    class Example;
    
    template <class T = void>
    class Example {};
    
    template <class T = void>
    class Example {};
    
    Example() -> Example<>;