Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 确定是否存在没有功能测试宏的类型_C++_Templates_Types - Fatal编程技术网

C++ 确定是否存在没有功能测试宏的类型

C++ 确定是否存在没有功能测试宏的类型,c++,templates,types,C++,Templates,Types,我想在不使用功能测试宏的情况下确定类型是否存在。以下是使用宏的想法: namespace real { struct foo final { static constexpr const char* name = "real::foo"; }; } #define real_foo_ 314 struct my_foo final { static constexpr const char* name = "my_foo"; }; namespa

我想在不使用功能测试宏的情况下确定类型是否存在。以下是使用宏的想法:

namespace real
{
    struct foo final { static constexpr const char* name = "real::foo"; };
}
#define real_foo_ 314

struct my_foo final { static constexpr const char* name = "my_foo"; };
namespace real
{
#if !real_foo_
    using foo = my_foo;
#endif
}
也就是说,
real::foo
如果存在,则应将其添加到“
real
foo
,否则将使用
my_foo
;后续代码使用
real::foo
w/o,而不知道或关心它是实际版本还是替换版本

实现同样的目标似乎是正确的想法:

#include <type_traits>
namespace real
{
    struct bar final { static constexpr const char* name = "real::bar"; };
}

struct my_bar final { static constexpr const char* name = "my_bar"; };

// https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678
template<typename, typename = void>
constexpr bool is_type_complete_v = false;
template<typename T>
constexpr bool is_type_complete_v<T, std::void_t<decltype(sizeof(T))>> = true;

namespace real { struct bar; }
namespace real
{
    using bar = std::conditional_t<is_type_complete_v<real::bar>, real::bar, my_bar>;
}
错误C2371:'real::bar':重新定义;不同的基本类型
消息:请参见“real::bar”的声明
错误C2079:“bar”使用未定义的结构“real::bar”

有没有一种方法可以使
real::bar
real::foo
一样工作,而不依赖于功能测试宏?请注意,与
real::foo
一样,
real::bar
的名称不能更改(例如,改为
real::real\u bar



(实际使用案例:C++14/C++17/C++20在C++11中实现的库功能;一旦使用
std::filesystem::path
的客户机代码编写完成,它就不必更改了。)

编译器抱怨您的代码,因为您试图创建两个同名实体。考虑改变

namespace real
{
    struct bar final { static constexpr const char* name = "real::bar"; };
}
差不多

namespace real
{
    struct absolutely_bar final { static constexpr const char* name = "real::bar"; };
}
...
namespace real { struct absolutely_bar; }
namespace real
{
    using bar = std::conditional_t<is_type_complete_v<real::absolutely_bar>, real::absolutely_bar, my_bar>;
}
名称空间实数
{
struct\u bar final{static constexpr const char*name=“real::bar”;};
}
...
命名空间实{struct\u bar;}
命名空间实数
{
使用bar=std::conditional\u t;
}

PS:创建这样的别名通常是一种不好的模式,因为它并不明显。

在代码中检查
currentVersion=>C++17
有什么不对?宏的用法不好。但有些是正确的(我认为分支从预处理器一个正确的)。预处理器指令的替代方法可能是使用工具链来选择要从生成中包括/排除的文件,从某个模板生成某个文件(
“real.h.in”
)。
namespace real
{
    struct bar final { static constexpr const char* name = "real::bar"; };
}
namespace real
{
    struct absolutely_bar final { static constexpr const char* name = "real::bar"; };
}
...
namespace real { struct absolutely_bar; }
namespace real
{
    using bar = std::conditional_t<is_type_complete_v<real::absolutely_bar>, real::absolutely_bar, my_bar>;
}