【发布时间】:2021-04-06 09:47:49
【问题描述】:
我正在尝试制作一种方法,如果可用,用户可以提供分析梯度函数,但如果没有,则默认使用数值梯度。
为此,我尝试了以下方法:
template<typename V, typename S, S (*Fun)(const V&)> V NumericGradient(const V& p)
{
const S e = 1.0e-6;
return {
Fun(p + V(e, 0, 0)) - Fun(p - V(e, 0, 0)) / S(2) * e,
Fun(p + V(0, e, 0)) - Fun(p - V(0, e, 0)) / S(2) * e,
Fun(p + V(0, 0, e)) - Fun(p - V(0, 0, e)) / S(2) * e,
};
}
template<typename V, typename S = decltype(V()[0])>
std::vector<V> DualContouring(
S (*DistanceFunction)(const V&),
V (*GradientFunction)(const V&) = NumericGradient<V, S, decltype(DistanceFunction)>,
const S span = S(50),
const unsigned int resolution = 100)
{
return {};
}
但是编译器失败并显示此消息(在实例化之后):
terrain_generation.cpp
../Src/examples/TerrainGeneration/terrain_generation.cpp: In function ‘std::vector<_RealType> DualContouring(S (*)(const V&), V (*)(const V&), S, unsigned int) [with V = Eigen::Matrix<float, 3, 1>; S = float]’:
../Src/examples/TerrainGeneration/terrain_generation.cpp:362:63: error: no matches converting function ‘NumericGradient’ to type ‘class Eigen::Matrix<float, 3, 1> (*)(const class Eigen::Matrix<float, 3, 1>&)’
362 | [](const Eigen::Vector3f& v) { return v.dot(v) - 10; });
| ^
In file included from ../Src/Engine/Renderer/Renderer.hpp:24,
from ../Src/examples/TerrainGeneration/terrain_generation.cpp:32:
../Src/Engine/Geometry/DualContouring.hpp:97:56: note: candidate is: ‘template<class V, class S, S (* Fun)(const V&)> V NumericGradient(const V&)’
97 | template<typename V, typename S, S (*Fun)(const V&)> V NumericGradient(const V& p)
| ^~~~~~~~~~~~~~~
../Src/examples/TerrainGeneration/terrain_generation.cpp:362:63: note: when instantiating default argument for call to ‘std::vector<_RealType> DualContouring(S (*)(const V&), V (*)(const V&), S, unsigned int) [with V = Eigen::Matrix<float, 3, 1>; S = float]’
362 | [](const Eigen::Vector3f& v) { return v.dot(v) - 10; });
| ^
../Src/examples/TerrainGeneration/terrain_generation.cpp: In function ‘void GenerateTerrain(Gallery&)’:
../Src/examples/TerrainGeneration/terrain_generation.cpp:362:63: error: no matches converting function ‘NumericGradient’ to type ‘class Eigen::Matrix<float, 3, 1> (*)(const class Eigen::Matrix<float, 3, 1>&)’
In file included from ../Src/Engine/Renderer/Renderer.hpp:24,
from ../Src/examples/TerrainGeneration/terrain_generation.cpp:32:
../Src/Engine/Geometry/DualContouring.hpp:97:56: note: candidate is: ‘template<class V, class S, S (* Fun)(const V&)> V NumericGradient(const V&)’
97 | template<typename V, typename S, S (*Fun)(const V&)> V NumericGradient(const V& p)
| ^~~~~~~~~~~~~~~
make[1]: *** [TerrainGeneration.make:156: obj/Debug/TerrainGeneration/terrain_generation.o] Error 1
make: *** [Makefile:39: TerrainGeneration] Error 2
make: Leaving directory '/home/makogan/vkengine/Generated'
Traceback (most recent call last):
File "build.py", line 139, in <module>
main()
File "build.py", line 106, in main
raise Exception("Compilation failed.")
Exception: Compilation failed.
我不确定那里的类型定义有什么问题。 NumericGradient 的实例化应该与预期的函数类型兼容。
这就是我尝试调用存根的方式:
auto contour = DualContouring<Eigen::Vector3f, float>(
[](const Eigen::Vector3f& v) { return v.dot(v) - 10; });
我在linux下用g++ 9.3编译。
替代问题
好的,我尝试完全删除默认参数并强制用户始终传递函数指针。
不知何故:
float (*Distance)(const Eigen::Vector3f&) = [](const Eigen::Vector3f& v) {
return v.dot(v) - 9;
};
auto contour = DualContouring<Eigen::Vector3f, float>(
Distance, NumericGradient<Eigen::Vector3f, float>, Distance);
编译失败并出现错误:
error: no matches converting function ‘NumericGradient’ to type ‘class Eigen::Matrix<float, 3, 1> (*)(const class Eigen::Matrix<float, 3, 1>&)’
365 | Distance, NumericGradient<Eigen::Vector3f, float>, Distance);```
Why? The template declaration should be fine.
【问题讨论】:
-
~能否给我们一个 DualContouring 的使用示例(带示例中使用的类型的定义)?~ Duh, V = Eigen::Matrix
; S = 浮动... -
如果你提到你正在使用的编译器(w/版本)也会很有帮助。
-
@PedroBoechat 我添加了请求的信息。
标签: c++ templates compiler-errors template-meta-programming