实现多类型算术运算符时如何解决"template argument deduction/substitution failure"
How do I solve "template argument deduction/substitution failure" when implementing multi-type arithmetic operators
我似乎找不到正确的实现方法,这似乎是最接近正确的方法,但我得到了模板参数推断错误。谁能指出我哪里出错了?
我正在尝试将算术功能添加到std::variant
而无需先std::get
:
#include <iostream>
#include <variant>
template<typename... Types>
class variant : public std::variant<Types...> {
private:
template <class Op, typename T, int index = 0>
decltype(auto) calc(const T& other) const {
if(sizeof...(Types) == 0 || index >= sizeof...(Types)){
return;
}
using ST = std::variant_alternative_t<index, std::variant<Types...>>;
if(std::holds_alternative<ST>(
std::variant<Types...>(*this)
)){
if(std::is_same<T, variant<Types...>>::value){
return Op()(std::get<ST>(*this), std::get<ST>(other));
}
else{
return Op()(std::get<ST>(*this), other);
}
}
return this->calc<Op, index+1>(other);
}
public:
using std::variant<Types...>::variant;
template <typename T>
decltype(auto) operator-(const T& other) const {
return this->calc<std::minus>(other);
}
// other operations will be added; std::plus, etc.
};
int main()
{
variant<int, double> vt1 = 2.3;
variant<int, double> vt2 = 5;
std::cout << "first: " << (vt1 - 2) << std::endl;
std::cout << "second: " << (vt2 - vt1) << std::endl;
return 0;
}
您有几个问题:
std::minus
不是一种类型,而是一种模板。它无法绑定到class Op
。您可能希望改用std::minus<>
。- 当您从
calc<Op, index>()
调用calc<Op, index + 1>()
时,您将获得无限递归。开头的if
条件没有帮助,因为编译器仍然必须生成该调用:此条件在运行时检查,而不是在编译时检查。你需要if constexpr
. - 返回类型的类型不一致
decltype(auto)
。所有未丢弃的分支都应返回相同的类型。 - 如果
*this
和other
持有不同的类型(在您的示例中,它们确实持有不同的类型(,Op()(std::get<ST>(*this), std::get<ST>(other))
将抛出。
与其修复所有这些并重新发明std::visit
,不如简单地定义自由函数并在实现中使用std::visit
:
namespace impl {
template<class T>
auto get_value(const T& t) {
return t;
}
template<class... Ts>
auto get_value(const std::variant<Ts...>& var) {
using T = std::common_type_t<Ts...>;
return std::visit([](T value) { return value; }, var);
}
template<class Op, class T, class U>
auto var_op(Op op, const T& t, const U& u) {
return op(get_value(t), get_value(u));
}
}
template<class... Ts, class U>
auto operator-(const std::variant<Ts...>& var, const U& u) {
return impl::var_op(std::minus<>{}, var, u);
}
template<class U, class... Ts>
auto operator-(const U& u, const std::variant<Ts...>& var) {
return impl::var_op(std::minus<>{}, u, var);
}
template<class... Ts, class... Us>
auto operator-(const std::variant<Ts...>& var1,
const std::variant<Us...>& var2) {
return impl::var_op(std::minus<>{}, var1, var2);
}
如果你想将这些函数限制在你自己的类my_variant
派生自std::variant
,你需要通过添加static_cast
来修复get_value()
,因为std::visit
使用一些不专门用于my_variant
的辅助类(如std::variant_size
(:
template<class... Ts>
class my_variant : public std::variant<Ts...> {
public:
using std::variant<Ts...>::variant;
};
...
namespace impl {
template<class... Ts>
auto get_value(const my_variant<Ts...>& var) {
using T = std::common_type_t<Ts...>;
return std::visit([](T value) { return value; },
static_cast<const std::variant<Ts...>&>(var));
}
}
相关文章:
- 表示"accepting anything for this template argument" C++概念的通配符
- 为什么编译器说"candidate template ignored: couldn't infer template argument 'InputIterator'"?
- 实现多类型算术运算符时如何解决"template argument deduction/substitution failure"
- 如何修复 eigen3 中的'non-type template argument is not a constant expression'?
- 通过"Value Template Argument"与常规阵列在堆栈中分配内存
- 模板类错误的向量:"Template argument 2 is invalid"
- 如何修复"static assertion failed: template argument not an integral type"错误?
- 如何在返回类型函数模板的专用化中使用派生类型?( "couldn't infer template argument" )
- "could not convert template argument"到自己的类型
- 表达式模板:错误 C2784 'could not deduce template argument'
- 需要帮助理解 GCC 给出"within a nested template argument list"错误的含义
- constexpr with std::array - "Non-type template argument is not a constant expression"
- "unspecialized class template can't be used as a template argument"是什么意思?
- MSVC:"use of class template requires template argument list" STL 容器内
- "missing template argument"是什么意思?
- std::map.insert "could not deduce template argument for..."
- "template argument deduction for class templates"是否应该推断出可变参数类模板的空参数包?
- 为什么此代码有 C2784 "could not deduce template argument"错误
- 即使使用强制转换,指针参数也"could not convert template argument"错误
- "use of class template requires template argument list"错误,即使使用了模板的模板,因此模板类是预期的