C++ 模板参数的演绎指南
我有一套结构类:C++ 模板参数的演绎指南,c++,templates,parameters,c++17,deduction-guide,C++,Templates,Parameters,C++17,Deduction Guide,我有一套结构类: template<typename T> struct Foo { T x_; T y_; constexpr Foo(T x, T y) : x_{x}, y_{y} {} }; template<typename T, typename U, template<U> class Func> class Bar { private: Foo<T> foo_; Func<U>
template<typename T>
struct Foo {
T x_;
T y_;
constexpr Foo(T x, T y) : x_{x}, y_{y} {}
};
template<typename T, typename U, template<U> class Func>
class Bar {
private:
Foo<T> foo_;
Func<U> func_
size_t n_;
public:
Bar(Foo<T> foo, size_t n, Func<U> func) :
foo_{foo},
n_{n},
func_{func}
{}
};
编辑-本节面向用户: 注意:上面是一个伪代码,其签名与我的类的表示形式相同。。。现在我又可以访问我的IDE了,这里是“真正的”源代码 Integrator.h
#pragma once
//#include <type_traits>
template <typename Field>
struct Limits {
Field lower;
Field upper;
constexpr Limits(Field a = 0, Field b = 0) :
lower{ a < b ? a : b },
upper{ a < b ? b : a }
{}
};
template <typename LimitType, typename Func>
class Integrator {
//static_assert(std::is_invocable_v<Func&>, "Invalid callable");
private:
Limits<LimitType> limits_;
size_t step_size_;
Func integrand_;
public:
Integrator(Limits<LimitType> limits, size_t stepSize, Func integrand) :
limits_{ limits },
step_size_{ stepSize },
integrand_{ integrand }
{}
constexpr auto evaluate() {
auto distance = limits_.upper - limits_.lower;
auto dx = distance / step_size_;
return calculate(dx);
}
private:
template<typename ValueType>
constexpr auto calculate(ValueType dx) {
ValueType result = 0.0;
for (size_t i = 0; i < step_size_; ++i) {
auto dy = integrand_(limits_.lower + i * dx);
auto area = dy * dx;
result += area;
}
return result;
}
};
//template <typename LimitType, typename Func>
//Integrator(Limits<LimitType>, size_t, Func)
//->Integrator<LimitType, Func>;
#pragma一次
//#包括
模板
结构极限{
场低;
田上;
constexpr限制(字段a=0,字段b=0):
下{a积分器;
main.cpp
#include <iostream>
#include <exception>
#include "Integrator.h"
double funcE(double x) {
return x;
}
template <typename T>
constexpr T funcA_t(T x) {
return x;
}
// This Works!
int main() {
try {
std::cout << "Integration of f(x) = x from a=3.0 to b=5.0\nwith an expected output of 8\n";
Integrator integratorA{ Limits{3.0, 5.0}, 10000, funcA };
std::cout << integratorA.evaluate() << '\n';
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
// This was failing to compile... but now seems to work for some reason...
int main() {
try {
std::cout << "Integration of f(x) = x from a=3.0 to b=5.0\nwith an expected output of 8\n";
Integrator integratorA{ Limits{3.0, 5.0}, 10000, funcA_t<double> };
std::cout << integratorA.evaluate() << '\n';
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
// Same as above...
Integrator integrator{ Limits{3.0, 5.0}, 10000, &funcA_t<double> };
// wasn't compiling...
#包括
#包括
#包括“Integrator.h”
双函数(双x){
返回x;
}
模板
constexpr T funcA_T(tx){
返回x;
}
//这管用!
int main(){
试一试{
std::cout首先,使用以下语法:
template <typename T, typename U, template <U> class Func>
以及相应的扣减指引:
template <typename T, typename U, template <typename> class Func>
Bar(Foo<T>, U, Func<U>) -> Bar<T, U, Func>;
为了确保它可以用U
类型的(左值)参数调用,只需设置一个类似于static\U assert
的约束:
#include <type_traits>
template <typename T, typename U, typename Func>
class Bar {
static_assert(std::is_invocable_v<Func&, U&>, "Invalid callable");
private:
Foo<T> foo_;
Func func_;
U n_;
public:
Bar(Foo<T> foo, U n, Func func) :
foo_{foo},
func_{func},
n_{n}
{}
};
或者,如果或需要,您可以使用std::enable\u使calculate
SFINAE友好:
template <typename ValueType>
constexpr auto calculate(ValueType dx)
-> std::enable_if_t<std::is_invocable_v<Func&, ValueType&>, ValueType> {
ValueType result = 0.0;
// ...
return result;
}
模板
constexpr自动计算(ValueType dx)
->std::如果启用,则启用{
ValueType结果=0.0;
// ...
返回结果;
}
U
您传递给bar1
的U
是int
funcA
是double(*)(double)
。对于某些F
来说,这不是F
。这不起作用…@Barry,U
不应该是int
它应该是double
或传递的函数对象的模板参数
,这就是我被难住的地方…好吧,double(*)(double)
也不能推导到F
。你确定不想只推导一个可调用的F
?是的,在模板化这个类之前,我最初使用std::function
作为这个参数。现在我正在尝试模板化它,并使它显式地constepr
。我的函数的签名是double func>(双x)
但现在它们也被模板化了。只使用单个参数并返回相同的类型。类的最后一个参数可以是单个变量的函数指针、函数对象、函子或lambda表达式。类将从其构造函数中存储它,并在其成员函数中调用它。您的示例很好,但e成员n
不是U
,而是size\U t
。t
是模板结构Foo
将使用的类型,U
应该是函数对象
,函数指针
,函数
,函数
,lambdas>传入时将使用的类型这是Bar
s成员函数的返回类型所必需的…U Bar::someInternalFunc()
。如果这对您有意义的话?它们需要在类型上匹配。但是,这个类在传递到构造函数之前对这些函数对象一无所知…@FrancisCugler我认为size\u t
是一个输入错误,因此我建议使用隐式推断指南。如果不是输入错误,那么就编写一个自定义推断ide。@FrancisCugler告诉我调用func\u
的位置和方式。否则,这只是猜测您实际需要什么。@FrancisCugler将static\u assert
放在calculate
函数中。如果该函数的参数与存储的可调用obejct不匹配,则是该函数的问题,而不是类本身的错误。
template <typename T, typename U, template <typename> class Func>
Bar(Foo<T>, U, Func<U>) -> Bar<T, U, Func>;
template <typename T, typename U, typename Func>
// ~~~~~~~^
#include <type_traits>
template <typename T, typename U, typename Func>
class Bar {
static_assert(std::is_invocable_v<Func&, U&>, "Invalid callable");
private:
Foo<T> foo_;
Func func_;
U n_;
public:
Bar(Foo<T> foo, U n, Func func) :
foo_{foo},
func_{func},
n_{n}
{}
};
template <typename ValueType>
constexpr auto calculate(ValueType dx) {
static_assert(std::is_invocable_v<Func&, ValueType&>, "Invalid value type");
ValueType result = 0.0;
// ...
return result;
}
template <typename ValueType>
constexpr auto calculate(ValueType dx)
-> std::enable_if_t<std::is_invocable_v<Func&, ValueType&>, ValueType> {
ValueType result = 0.0;
// ...
return result;
}