gpt4 book ai didi

没有重复定义的 C++ 模板匹配类型

转载 作者:行者123 更新时间:2023-11-28 04:40:16 26 4
gpt4 key购买 nike

我正在围绕 std::function 创建一个模板包装器。为了匹配返回 void 的函数,我将 std::monostate 作为我的 Unit 类型。我一直在尝试为我的函数包装器类型创建两个可变参数模板,一个

template<Unit, Args...>

还有一个

template<T, Args...> where T != Unit.

这是我通过使用 enable_if 获得的最接近结果。

#include <functional>
#include <variant>

namespace func {
// Declare unit type
typedef std::monostate Unit;

// Empty type, maybe use this instead of monostate
template<typename ... ts>
struct Term {};

// Variables
template<typename T>
struct Term<T>
{
T val;
// Constructor
Term(T in): val(in) {}

// Call op just returns the value
T operator() () const {
return this->val;
}
};

// Functions that return void
template <typename T,
typename ... Args,
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
struct Term<Args...>
{
// Void returning function
const std::function<void(Args...)> body;

// Void returning constructor
Term(std::function<void(Args...)> func): body(func) {}

// Void function Caller
void operator() (const Args&& ...a) const {
this->body(std::forward<Args>(a)...);
}
};

// Functions that return T
template <typename T,
typename ... Args,
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
struct Term<T, Args...>
{
// T returning function
const std::function<T(Args...)> body;

// T returning constructor
Term(std::function<T(Args...)> func): body(func) {}

// T returning function Caller
T operator() (const Args&& ...a) const {
return this->body(std::forward<Args>(a)...);
}
};

}

但是,在第一种情况下,我收到关于不可推导参数 T 的错误。但是,我已经通过我的 enable_if 模板参数知道该参数将属于 Unit 类型。如何让编译器接受这两个定义?

错误:

$ clang++ -std=c++17 terms.hpp -pedantic
terms.hpp:29:18: error: default template argument in a class template partial specialization
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
^
terms.hpp:30:9: error: class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct Term<Args...>
^~~~~~~~~~~~~
terms.hpp:27:21: note: non-deducible template parameter 'T'
template <typename T,
^
terms.hpp:29:7: note: non-deducible template parameter (anonymous)
typename = std::enable_if_t<std::is_same<T, Unit>::value>>
^
terms.hpp:47:18: error: default template argument in a class template partial specialization
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
^
terms.hpp:48:9: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct Term<T, Args...>
^~~~~~~~~~~~~~~~
terms.hpp:47:7: note: non-deducible template parameter (anonymous)
typename = std::enable_if_t<!std::is_same<T, Unit>::value>>
^
4 errors generated.

编辑:应该这样使用

auto c = Term<int>(42);
auto fun = Term<int, int, int>([](int a, int b) { return a + b; });

std::cout << c() << std::endl;
std::cout << fun(3,4) << std::endl;

最佳答案

您目前在模板特化方面遇到的问题是 struct Term<Args...>struct Term<T, Args...>互不排斥,可以匹配相同的事物。因此,我建议您将这两种情况统一为一种情况,并在重载调用运算符上将 SFINAE 统一起来。

这种方法当然有一些局限性,但这些只是继承自您原来的方法。例如,不可能包装一个不接受参数但返回一个值(与标量不明确)的函数。

#include <functional>
#include <iostream>
#include <variant>

namespace func {
// Declare unit type
typedef std::monostate Unit;

// Empty type, maybe use this instead of monostate
template<typename...>
struct Term;

// Variables
template<typename T>
struct Term<T>
{
T val;
// Constructor
Term(T in): val(in) {}

// Call op just returns the value
T operator() () const {
return this->val;
}
};

// Functions that return void
template <typename T, typename ... Args>
struct Term<T, Args...>
{
using R = typename std::conditional<std::is_same<T, Unit>::value,void,T>::type;
// Void returning function
const std::function<R(Args...)> body;

// Void returning constructor
Term(std::function<R(Args...)> func): body(func) {}

// Void function Caller
template <typename U = R>
typename std::enable_if<std::is_same<U, Unit>::value,void>::type
operator() (Args&& ...a) const {
this->body(std::forward<Args>(a)...);
}

// T returning function Caller
template <typename U = R>
typename std::enable_if<!std::is_same<U, Unit>::value,T>::type
operator() (Args&& ...a) const {
return this->body(std::forward<Args>(a)...);
}

};
}

int main() {
auto c = func::Term<int>(42);
auto fun = func::Term<int, int, int>([](int a, int b) { return a + b; });

std::cout << c() << std::endl;
std::cout << fun(3,4) << std::endl;
}

Live example

关于没有重复定义的 C++ 模板匹配类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50321030/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com