英文:
CTAD fails for templated base class
问题
考虑以下简单的结构。我从Entity派生了一个类类型EntityView,它允许我指定一个分配器(如果我想要的话),如果我不指定,它应该回退到默认的模板参数。然而,编译器抱怨它无法推断模板参数:
#include <iostream>
#include <stdexcept>
#include <string>
#include <memory>
template <typename StringType = std::string>
struct Entity {
Entity(int) {
std::cout << "Hello World!" << std::endl;
}
};
template <typename Allocator = std::allocator<int>>
struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
using Entity<std::basic_string<char, std::char_traits<char>, Allocator>>::Entity;
};
int main() {
EntityView myview{2};
}
产生的错误信息(gcc):
<source>: In function 'int main()':
<source>:19:24: error: class template argument deduction failed:
19 | EntityView myview{2};
| ^
<source>:19:24: error: no matching function for call to 'EntityView(int)'
<source>:14:8: note: candidate: 'template<class Allocator> EntityView()-> EntityView<Allocator>'
14 | struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
| ^~~~~~~~~~
<source>:14:8: note: template argument deduction/substitution failed:
<source>:19:24: note: candidate expects 0 arguments, 1 provided
19 | EntityView myview{2};
| ^
<source>:14:8: note: candidate: 'template<class Allocator> EntityView(EntityView<Allocator>)-> EntityView<Allocator>'
14 | struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
| ^~~~~~~~~~
<source>:14:8: note: template argument deduction/substitution failed:
<source>:19:24: note: mismatched types 'EntityView<Allocator>' and 'int'
19 | EntityView myview{2};
| ^
问题似乎在于它尝试进行类模板参数推断(CTAD),但在构造函数中没有什么可以从中推导出来,也不在继承的类中。是否有任何方法让编译器接受默认的模板参数而不是尝试推断它?
英文:
Consider the following simple construct. I derive a class type EntityView from Entity which allows me to specify an allocator if I want to, and if I don't it should fall back to the defaulted template parameter. Yet the compiler complains that it can't derive template arguments:
#include <iostream>
#include <stdexcept>
#include <string>
#include <memory>
template <typename StringType = std::string>
struct Entity {
Entity(int) {
std::cout << "Hello World!" << std::endl;
}
};
template <typename Allocator = std::allocator<int>>
struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
using Entity<std::basic_string<char, std::char_traits<char>, Allocator>>::Entity;
};
int main() {
EntityView myview{2};
}
Yields (gcc):
<source>: In function 'int main()':
<source>:19:24: error: class template argument deduction failed:
19 | EntityView myview{2};
| ^
<source>:19:24: error: no matching function for call to 'EntityView(int)'
<source>:14:8: note: candidate: 'template<class Allocator> EntityView()-> EntityView<Allocator>'
14 | struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
| ^~~~~~~~~~
<source>:14:8: note: template argument deduction/substitution failed:
<source>:19:24: note: candidate expects 0 arguments, 1 provided
19 | EntityView myview{2};
| ^
<source>:14:8: note: candidate: 'template<class Allocator> EntityView(EntityView<Allocator>)-> EntityView<Allocator>'
14 | struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
| ^~~~~~~~~~
<source>:14:8: note: template argument deduction/substitution failed:
<source>:19:24: note: mismatched types 'EntityView<Allocator>' and 'int'
19 | EntityView myview{2};
| ^
The problem seems to be that it is trying to do CTAD, however there's nothing to be derived from the constructor, also not in the inherited class. Is there any way to have the compiler just accept the default template argument instead of trying to deduce it?
答案1
得分: 4
只定义一个通用的扣除指南:
#include <iostream>
#include <stdexcept>
#include <string>
#include <memory>
template <typename StringType = std::string>
struct Entity {
Entity(int) {
std::cout << "你好,世界!" << std::endl;
}
template <typename T>
Entity(T) {
std::cout << "模板" << std::endl;
}
template<typename... Args>
Entity(Args&&...) {
std::cout << "可变参数" << std::endl;
}
};
template <typename Allocator = std::allocator<int>>
struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
using Entity<std::basic_string<char, std::char_traits<char>, Allocator>>::Entity;
};
template<typename... Args>
EntityView(Args&&...) -> EntityView<>;
int main() {
{ EntityView myview{2}; }
{ EntityView myview{2.}; }
{ EntityView myview{2, 3}; }
}
英文:
Just define a universal deduction guide:
#include <iostream>
#include <stdexcept>
#include <string>
#include <memory>
template <typename StringType = std::string>
struct Entity {
Entity(int) {
std::cout << "Hello World!" << std::endl;
}
template <typename T>
Entity(T) {
std::cout << "template" << std::endl;
}
template<typename... Args>
Entity(Args&&...) {
std::cout << "variadic" << std::endl;
}
};
template <typename Allocator = std::allocator<int>>
struct EntityView : public Entity<std::basic_string<char, std::char_traits<char>, Allocator>> {
using Entity<std::basic_string<char, std::char_traits<char>, Allocator>>::Entity;
};
template<typename... Args>
EntityView(Args&&...) -> EntityView<>;
int main() {
{ EntityView myview{2}; }
{ EntityView myview{2.}; }
{ EntityView myview{2, 3}; }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论