首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CTAD不适用于默认模板参数?

CTAD不适用于默认模板参数?
EN

Stack Overflow用户
提问于 2022-07-18 16:56:56
回答 1查看 74关注 0票数 0

当我有一个接受向量的类对象时,比较下面的情况。未推导的参数T可以用默认的模板参数很好地替换:

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

template <typename T = int>
struct container
{
    container(std::vector<T> vec) {}
};

int main()
{
    container C = std::vector{1,2,3,4,5};
}

对于我的班级来说,情况并非如此,因为情况要复杂一些( struct+container+:+public+obj { ++++container(obj<0>+init)+{} }; int+main() { ++++container<5>+some_container+=+obj{1,2,5,2,obj{1,2,33},2,2}; }'),l:'5',n:'0',o:'C+++source+#1',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gsnapshot,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c++,libs:!(),options:'--std=c++17+-O2',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+gcc+(trunk)+(C++,+Editor+#1,+Compiler+#1)',t:'0')),k:50,l:'4',m:43.35736354273945,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compilerName:'x86-64+clang+(trunk)',editorid:1,fontScale:14,fontUsePx:'0',j:1,wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+gcc+(trunk)+(Compiler+#1)',t:'0')),header:(),l:'4',m:56.64263645726055,n:'0',o:'',s:0,t:'0')),k:50,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4))">CompilerExplorer )

代码语言:javascript
复制
#include <cstdio>
#include <initializer_list>
#include <variant>

template <size_t> struct obj;

template<size_t Vs>
using val = std::variant<std::monostate, int, struct obj<Vs>>;

template <size_t Vs = 0>
struct obj
{
    obj() = default;
    obj(std::initializer_list<val<Vs>> init) {
        printf("initializer of object called, Vs = %d\n", Vs);
    }
};


template <size_t Vs = 0>
struct container : public obj<Vs>
{
    container(obj<0> init) {}
};


int main()
{
    container<5> some_container = obj{1,2,5,2,obj{1,2,33},2,2};
}

如果出现以下错误,这将失败:

代码语言:javascript
复制
<source>: In function 'int main()':
<source>:29:57: error: class template argument deduction failed:
   29 |     container<5> some_container = obj{1,2,5,2,obj{1,2,33},2,2};
      |                                                         ^
<source>:29:57: error: no matching function for call to 'obj(int, int, int)'
<source>:14:5: note: candidate: 'template<long unsigned int Vs> obj(std::initializer_list<std::variant<std::monostate, int, obj<Vs> > >)-> obj<<anonymous> >'
   14 |     obj(std::initializer_list<val<Vs>> init) {
      |     ^~~

但是,当我在容器实例化中补充模板专门化obj<0> (在main中)时,它可以工作。你知道为什么这对我的课不起作用吗?我怎样才能解决它?我不想强迫用户每次指定模板。

EN

回答 1

Stack Overflow用户

发布于 2022-07-18 17:13:24

这个问题在更简单的情况下已经存在。

代码语言:javascript
复制
auto o = obj{1,2,33};

从而产生此错误:

代码语言:javascript
复制
<source>:29:24: error: class template argument deduction failed:
   29 |     auto o = obj{1,2,33};
      |                        ^
<source>:29:24: error: no matching function for call to 'obj(int, int, int)'
<source>:14:5: note: candidate: 'template<long unsigned int Vs> obj(std::initializer_list<std::variant<std::monostate, int, obj<Vs> > >)-> obj<<anonymous> >'
   14 |     obj(std::initializer_list<val<Vs>> init) {
      |     ^~~
<source>:14:5: note:   template argument deduction/substitution failed:
<source>:29:24: note:   mismatched types 'std::initializer_list<std::variant<std::monostate, int, obj<Vs> > >' and 'int'
   29 |     auto o = obj{1,2,33};

因此,编译器无法推断出这三个int应该是一个初始化程序列表。如果在它们周围添加额外的大括号,编译器就会意识到这实际上应该是一个列表参数,而不是三个单独的参数,它可以工作:

代码语言:javascript
复制
auto o = obj{{1,2,33}};

这也涉及到更复杂的情况:

代码语言:javascript
复制
container some_container = obj{{1,2,5,2,obj{{1,2,33}},2,2}};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73025961

复制
相关文章

相似问题

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