小编use*_*989的帖子

为什么允许函数声明中的前向声明?

在阅读访问者模式时,我遇到了这段代码:

virtual void visit(class Composite *, Component*) = 0;
Run Code Online (Sandbox Code Playgroud)

这是一个成员函数,它似乎是Composite在其参数内声明类.我只用一个普通的函数试过这个,就像这样:

void accept(class A a);
Run Code Online (Sandbox Code Playgroud)

对于A我尚未声明或定义的某些类,代码工作正常.为什么允许这样做?如果有的话,它是否与前线宣布不同?最近标准中有什么变化吗?


很多人都声称这是C的遗留物,但是为什么这个代码在C++中编译得很好,而不是C?

#include <stdio.h>
int process(struct A a);

struct A{
    int x;
};

int process(struct A a){
    return a.x;
}

int main(void)
{
    struct A a = {2};
    printf("%d", process(a));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ c++11

15
推荐指数
2
解决办法
2638
查看次数

部分模板特化触发static_asserts

考虑这段代码

template <typename T>
struct delay : std::false_type{};

template <typename T>
struct my_typelist {
    static_assert(delay<T>{}, "");
};

template <typename Tuple>
struct test;

template <typename T>
struct test<my_typelist<T>> {
    void pass(){}
};

template <typename T>
void fail(const test<T> &){}

int main()
{
    test<my_typelist<int>> t;
    t.pass();
    fail(t);
}
Run Code Online (Sandbox Code Playgroud)

没有调用fail()代码编译并运行正常.但是,t在任何函数中使用似乎都会static_assertmy_typelist类中触发,即使该类从未实例化.尽管这个例子是人为的,std::tuple但是我在一个内部使用了不完整的类型遇到了同样的问题,尽管我只是用作std::tuple一个类型列表并且从未实例化它.

为什么static_assert只有在我将变量用作参数时才触发,而不是在我调用成员函数时?在什么情况下my_typelist实例化,什么时候不实例?

请注意,我会使用可变参数模板,但无论如何都会发生错误,因此我选择使用最小公分母.

c++ c++11

13
推荐指数
2
解决办法
563
查看次数

如何创建类型列表以扩展为元组?

我正在尝试创建一个具有传递给它的所有类型的元组的类.我希望它将类型列表作为模板参数,并使用该列表中的类作为内部元组将包含的类.目前,我有类似的东西,实际上并没有编译.

template<class ... T>
struct ComponentList {};

template<ComponentList<typename ...T> >
class ComponentManager{
    std::tuple<T...> components;
};
Run Code Online (Sandbox Code Playgroud)

我想ComponentList成为自己的类型的原因是因为我想稍后传入其他类型列表.这可能吗?如果没有,那会有什么替代方案呢?

c++ c++11 c++14

9
推荐指数
1
解决办法
861
查看次数

漂亮的sfinae与static_assert

我正在尝试创建一个将注册接收器的事件管理器.为此,我希望能够std::function使用给定的参数构造一个.但是,我希望最终用户可以轻松理解错误.我想用SFINAE和类型依赖这样做static_assert但我遇到了麻烦,因为这两个函数在有效输入上变得模糊不清.此外,我希望有多个错误原因,用户可以收到.由于存在两个故障点(提供无效的仿函数并提供错误的事件类型),我希望总共有3个函数,第一个是正确输入的函数,然后是不正确的输入滴漏(而不是有4个函数用于每个国家的组合).

这可以用c ++ 17解决,if constexpr但我的目标平台是c ++ 14,因此需要使用其他方法.

我当前的尝试(仅检查一个错误状态):

template <typename Event, typename Func>
auto register(Func &&func)
-> decltype(func_t<Event>(std::forward<Func>(func)), void()) {}

template <typename Event, typename Func>
void register(Func &&) {
    static_assert(meta::delay_v<Func>, "Function object cant be constructed by function");
}
Run Code Online (Sandbox Code Playgroud)

meta::delay_v等于false但依赖于其参数,因此在static_assert调用函数之前不会触发.


一个更复杂的用例就是

template <typename Event, typename Func>
auto register(Func &&func)
-> decltype(func_t<Event>(std::forward<Func>(func))
            ,meta::is_in_tuple<Event, Events_Tuple>
            ,void()) {}
Run Code Online (Sandbox Code Playgroud)

因此,如果第一次测试失败(func_t构造),那么我们就static_assert会这样做,如果第二次测试失败,我们就static_assert会这样做.因此,如果第一次测试失败,无论第二次测试如何,我们都会失败一些静态断言.然后,如果第一次测试通过,我们将打印关于第二次测试失败的信息.不必重写测试将是一个非常好的奖金.

c++ templates sfinae c++14

7
推荐指数
1
解决办法
674
查看次数

为什么你使用相机空间而不是模型空间用于法线?

我正在学习OpenGL图形,并且正在进入阴影中.我正在阅读的教程告诉我将法线和光矢量转换为相机空间.为什么是这样?你为什么不能在模型空间中保持坐标?

对此的后续问题是如何处理模型转换.我无法找到明确的答案.我目前有这个代码:

vec3 normCamSpace = normalize(mat3(V) * normal);"
vec3 dirToLight = (V*vec4(lightPos, 0.0)).xyz;"
float cosTheta = clamp(dot(normCamSpace, dirToLight),0,1);"
Run Code Online (Sandbox Code Playgroud)

V是视图矩阵或相机矩阵.当模型在位置,旋转和比例上发生变化时,我不确定如何移动或编辑灯光.

c++ opengl math

6
推荐指数
1
解决办法
3718
查看次数

如何使用派生参数将函数转换为带有基本参数的函数?

我有一个名为的类Reciever,它有一个名为的函数recieve(const Event *),其中Event继承自BaseEvent.我想创建一个绑定到该类的特定实例.该实例被调用rec.为此,我使用:

void(Reciever::*func)(const Event *) = &Reciever::recieve;
auto recievePtr = std::bind(func, &rec, std::placeholders::_1);
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将其存储在向量中时,我必须指定一个std::function将a BaseEvent作为输入而不是a Event,如下所示:

std::vector<std::function<void(const BaseEvent*)>>
Run Code Online (Sandbox Code Playgroud)

我该如何投射,recievePtr以便将其正确存储在矢量中?这甚至可能吗?使用指向a的函数指针的问题BaseEvent是,Reciever可以使用多个recieve()方法,这些方法都具有不同的派生类BaseEvent

c++ c++11

6
推荐指数
1
解决办法
136
查看次数

传递给基类时,类定义是否完整?

我正在尝试编写一个包含static constexpr派生类型的CRTP ,因为这对于一个类是不可能的.这段代码在GCC中编译得很好,但是clang抱怨这Derived是一个不完整的类型.哪一个是对的?

template<class T>
class Base {
public:
    static constexpr T a = T(1), b = T(20);
};

class Derived : public Base<Derived> {
public:
    int x;
    constexpr Derived(int x) : x(x) {}
};
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++11

6
推荐指数
1
解决办法
179
查看次数

如何在《子弹物理》中控制玩家角色?

我不知道你应该如何控制子弹中的玩家角色。我读到的方法是使用提供的 btKinematicCharacterController。我还从演示中看到了使用 btDynamicCharacterController 的方法。然而,手册中指出运动控制器有几个突出的问题。这仍然是首选路径吗?如果是这样,有这方面的教程或文档吗?我发现的只是演示中的代码片段,以及 Ogre 控制器的使用,但我不使用它。

如果这不是应该走的路,那么有人会向我指出正确的解决方案。我是Bullet新手,想要一个简单、简单的解决方案。我目前拥有的是将 btKinematicCharacterController 的各个部分拼凑在一起。

这是我用来设置控制器的代码:

playerShape = new btCapsuleShape(0.25, 1);
ghostObject= new btPairCachingGhostObject();
ghostObject->setWorldTransform(btTransform(btQuaternion(0,0,0,1),btVector3(0,20,0)));
physics.getWorld()->getPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
ghostObject->setCollisionShape(playerShape);
ghostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
controller = new btKinematicCharacterController(ghostObject,playerShape,0.5);
physics.getWorld()->addCollisionObject(ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
physics.getWorld()->addAction(controller);
Run Code Online (Sandbox Code Playgroud)

这是我用来访问控制器位置的代码:

trans = controller->getGhostObject()->getWorldTransform();
camPosition.z = trans.getOrigin().z();
camPosition.y = trans.getOrigin().y()+0.5;
camPosition.x = trans.getOrigin().x();
Run Code Online (Sandbox Code Playgroud)

我控制它的方式是通过setWalkDirection()和jump()(如果canJump()为true)。

现在的问题是,角色有点兴奋,然后从静态地板上掉下来。显然这不是有意的。这是因为缺乏刚体吗?如何整合它?

事实上,现在它只是按其应有的方式掉落,但随后慢慢地沉入地板。

我已将这条线移至创建动态世界后的右侧

physics.getWorld()->getPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
Run Code Online (Sandbox Code Playgroud)

现在是这样的:

broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
Run Code Online (Sandbox Code Playgroud)

我还使用从搅拌机导入的 .bullet 文件(如果相关的话)。

问题出在子弹文件上,该文件现已修复(碰撞盒不起作用)。但还是会出现心慌、时不时爬不上去、从高处瞬间跳下来等问题。

c++ bulletphysics

5
推荐指数
1
解决办法
1万
查看次数

如何将模板函数声明为模板化嵌套类的朋友?

如何get在可以访问私有构造函数的封闭范围中创建函数outer<T>::inner<U>

template <typename T>
struct outer {
    template <typename U>
    class inner {
        inner() {}
    public:
        friend inner get(outer&) {
            return {};
        }
    };
};


int main() {
    outer<int> foo;
    outer<int>::inner<float> bar = get<float>(foo);
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试通过制作inner一个template <typename V, typename W> friend inner<V> get(outer<W>&);但却无法正常工作来宣布它.

c++ templates friend

4
推荐指数
1
解决办法
341
查看次数

JSONCPP 合并链接错误

我正在尝试使用 jsoncpp(最新版本)的合并版本,但它产生了未解决的外部符号链接错误。我使用的代码是

#include <json/json.h>

int main(){
   Json::Value root;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

它给了我错误

1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Json::Value::~Value(void)" (??1Value@Json@@QAE@XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Json::Value::Value(enum Json::ValueType)" (??0Value@Json@@QAE@W4ValueType@1@@Z) referenced in function _main
Run Code Online (Sandbox Code Playgroud)

c++ linker-errors jsoncpp

3
推荐指数
1
解决办法
5376
查看次数