检查参数是否存在的 C++ 概念不起作用
C++ concept that checks if parameter present doesn't work
我的项目中有一些 class 层次结构:
template<typename T>
class __declspec(dllexport) EnableSharedFromThis
{
public:
...
uint64* last_valid_counter = nullptr;
};
class __declspec(dllexport) Material : public Object, public EnableSharedFromThis<Material>
{
...
}
class __declspec(dllexport) Material3D : public Material
{
...
}
我有一个概念
template<typename T>
concept CanEnableShared = requires
{
{ T::last_valid_counter } -> std::same_as<uint64*>;
};
但是当我这样做的时候
auto a = CanEnableShared<Material3D>;
auto b = CanEnableShared<Material>;
auto c = CanEnableShared<EnableSharedFromThis<Material>>;
我三遍都得到了false
。我做错了什么?
更新:
将我的概念更改为:
template<typename T>
concept CanEnableShared = requires
{
{ T::last_valid_counter } -> std::same_as<uint64*&>;
};
现在 2 和 3 检查 returns true,但首先检查 returns false
不要觉得这可能是个问题,但是所有classes都标记为__declspec(dllexport)
并且Material
也继承了一些Object
class
更新:
好吧,我认为这是因为在其他 class 我写了
Shared(T* ptr) requires CanEnableShared<T>
: ptr_(ptr)
, counter_(new uint64(1))
{
ptr->last_valid_counter = counter_;
}
Shared(T* ptr)
: ptr_(ptr)
, counter_(new uint64(1))
{
}
应该简化成什么
Shared(T* ptr)
: ptr_(ptr)
, counter_(new uint64(1))
{
if constexpr (CanEnableShared<T>)
{
ptr->last_valid_counter = counter_;
}
}
Shared<T>
是我自己对 std::shared_ptr<T>
的类比
豪威尔!
我的项目中有 2 个模块:Engine
和 Game
。所有这些代码都来自引擎模块,它在 Engine
中工作,但是当我 link 它是 dll 到 Game
时它不起作用。此外,Game
模块中的 static_assert(CanEnableShared<Material3D>)
没有效果,概念匹配,但是当我跟踪上面的构造函数时,它绕过了我的 constexpr。概念有一些 dll-specific 行为吗?或者对于 constexpr?我怀疑,它与 objects 的编译方式和 linked
有某种关系
在使用 Shared<Material3D>
的 Game
中的 header 之上添加 #include "Engine/Material3D.h"
解决了问题,但这不是我想要的。看起来我必须在我引用的 header 中包含每个 class 的 header,前向声明在这种情况下不起作用
前向声明似乎只有在同一个模块中出现时才会被正确检查
在{ expr } -> concept
中,expr
的类型是determined as if by decltype((expr))
。
decltype((T::last_valid_counter))
是 uint64 *&
,所以这就是您需要传递给 std::same_as
.
的内容
有趣的是,Clang 似乎有一个错误,因为它似乎使用了 decltype(expr)
。
我的项目中有一些 class 层次结构:
template<typename T>
class __declspec(dllexport) EnableSharedFromThis
{
public:
...
uint64* last_valid_counter = nullptr;
};
class __declspec(dllexport) Material : public Object, public EnableSharedFromThis<Material>
{
...
}
class __declspec(dllexport) Material3D : public Material
{
...
}
我有一个概念
template<typename T>
concept CanEnableShared = requires
{
{ T::last_valid_counter } -> std::same_as<uint64*>;
};
但是当我这样做的时候
auto a = CanEnableShared<Material3D>;
auto b = CanEnableShared<Material>;
auto c = CanEnableShared<EnableSharedFromThis<Material>>;
我三遍都得到了false
。我做错了什么?
更新:
将我的概念更改为:
template<typename T>
concept CanEnableShared = requires
{
{ T::last_valid_counter } -> std::same_as<uint64*&>;
};
现在 2 和 3 检查 returns true,但首先检查 returns false
不要觉得这可能是个问题,但是所有classes都标记为__declspec(dllexport)
并且Material
也继承了一些Object
class
更新:
好吧,我认为这是因为在其他 class 我写了
Shared(T* ptr) requires CanEnableShared<T>
: ptr_(ptr)
, counter_(new uint64(1))
{
ptr->last_valid_counter = counter_;
}
Shared(T* ptr)
: ptr_(ptr)
, counter_(new uint64(1))
{
}
应该简化成什么
Shared(T* ptr)
: ptr_(ptr)
, counter_(new uint64(1))
{
if constexpr (CanEnableShared<T>)
{
ptr->last_valid_counter = counter_;
}
}
Shared<T>
是我自己对 std::shared_ptr<T>
豪威尔!
我的项目中有 2 个模块:Engine
和 Game
。所有这些代码都来自引擎模块,它在 Engine
中工作,但是当我 link 它是 dll 到 Game
时它不起作用。此外,Game
模块中的 static_assert(CanEnableShared<Material3D>)
没有效果,概念匹配,但是当我跟踪上面的构造函数时,它绕过了我的 constexpr。概念有一些 dll-specific 行为吗?或者对于 constexpr?我怀疑,它与 objects 的编译方式和 linked
在使用 Shared<Material3D>
的 Game
中的 header 之上添加 #include "Engine/Material3D.h"
解决了问题,但这不是我想要的。看起来我必须在我引用的 header 中包含每个 class 的 header,前向声明在这种情况下不起作用
前向声明似乎只有在同一个模块中出现时才会被正确检查
在{ expr } -> concept
中,expr
的类型是determined as if by decltype((expr))
。
decltype((T::last_valid_counter))
是 uint64 *&
,所以这就是您需要传递给 std::same_as
.
有趣的是,Clang 似乎有一个错误,因为它似乎使用了 decltype(expr)
。