类似于;如果constexpr";但是对于类定义 > CONEXPRPR 是C++程序中的预处理器的一个重要步骤。但是,它只在函数中起作用-如本例中所示: enum class OS { Linux, MacOs, MsWindows, Unknown }; #if defined(__APPLE__) constexpr OS os = OS::MacOs; #elif defined(__MINGW32__) constexpr OS os = OS::MsWindows; #elif defined(__linux__) constexpr OS os = OS::Linux; #else constexpr OS os = OS::Unknown; #endif void printSystem() { if constexpr (os == OS::Linux) { std::cout << "Linux"; } else if constexpr (os == OS::MacOs) { std::cout << "MacOS"; } else if constexpr (os == OS::MsWindows) { std::cout << "MS Windows"; } else { std::cout << "Unknown-OS"; } }

类似于;如果constexpr";但是对于类定义 > CONEXPRPR 是C++程序中的预处理器的一个重要步骤。但是,它只在函数中起作用-如本例中所示: enum class OS { Linux, MacOs, MsWindows, Unknown }; #if defined(__APPLE__) constexpr OS os = OS::MacOs; #elif defined(__MINGW32__) constexpr OS os = OS::MsWindows; #elif defined(__linux__) constexpr OS os = OS::Linux; #else constexpr OS os = OS::Unknown; #endif void printSystem() { if constexpr (os == OS::Linux) { std::cout << "Linux"; } else if constexpr (os == OS::MacOs) { std::cout << "MacOS"; } else if constexpr (os == OS::MsWindows) { std::cout << "MS Windows"; } else { std::cout << "Unknown-OS"; } },c++,class,c-preprocessor,c++17,if-constexpr,C++,Class,C Preprocessor,C++17,If Constexpr,我(几乎)确信这是根据C++17规范,如果constexpr只在函数体中起作用,那么——但我的问题是: Q1如何在函数中实现类似于if constexpr的效果-对于C++1z/C++14中的类和全局作用域?我不是在这里要求对模板专门化进行另一种解释。。。但它的简单性类似于if constexpr Q2对于上述范围,是否有扩展C++的计划?< /P> 在C++1z/C++14中,对于类和全局作用域,如何实现类似于函数中if constexpr的效果?我不是在这里要求对模板专门化进行另一种解释

我(几乎)确信这是根据C++17规范,如果constexpr只在函数体中起作用,那么
——但我的问题是:

Q1如何在函数中实现类似于
if constexpr
的效果-对于C++1z/C++14中的类和全局作用域?我不是在这里要求对模板专门化进行另一种解释。。。但它的简单性类似于
if constexpr

<强> Q2对于上述范围,是否有扩展C++的计划?< /P> 在C++1z/C++14中,对于类和全局作用域,如何实现类似于函数中if constexpr的效果?我不是在这里要求对模板专门化进行另一种解释

你基本上只是说,“我想要模板专门化,但不需要所有讨厌的模板专门化。”

如果constexpr
是根据编译时构造更改函数行为的工具。模板特化是C++提供的基于编译时构造的定义更改的工具。它是C++提供的唯一的工具。 现在,对于初始化变量的过于简单的情况,始终可以创建并调用lambda。C++17为lambda提供了
constexpr
支持,lambda可以使用
if-constexpr
来决定返回什么值

是否有扩展上述范围的C++计划?< /P> 没有,过去几年中没有一个研究这个领域

而且他们不太可能做到这一点。

索引类型:

template<std::size_t I>
using index = std::integral_constant<std::size_t, I>;
dispatch
获取一组编译时bool并返回lambda。此lambda通过完美转发与第一个真正编译时bool匹配的第一个元素返回:

template<class...Bools>
constexpr auto dispatch(Bools...bools) {
  constexpr auto index = first_truth(bools...);

  return [](auto&&...fs){
    return std::get< decltype(index){} >(
      std::forward_as_tuple( decltype(fs)(fs)... )
    );
  };
}
模板
constexpr自动调度(Bools…Bools){
constexpr自动索引=第一个真理(bools…);
返回[](自动和…fs){
return std::get(
标准::转发作为元组(decltype(fs)(fs)…)
);
};
}
编译时bool类型:

template<bool b>
using bool_t = std::integral_constant<bool, b>;
template<bool b>
bool_t<b> bool_k{};
模板
使用bool_t=std::integral_常数;
模板
bool_t bool_k{};
现在我们解决您的问题:

const char* const osName = 
  dispatch(
    bool_k<os == OS::Linux>,
    bool_k<os == OS::MacOs>,
    bool_k<os == OS::MsWindows>
  )(
    "Linux",
    "MacOS",
    "MS Windows",
    "Unknown"
  );
const char*const osName=
派遣(
布卢克,
布卢克,
布卢克
)(
“Linux”,
“MacOS”,
“微软视窗”,
“未知”
);
它应该近似于编译时开关。我们可以再多做点工作,把布尔值和论点联系得更紧密

未编译的代码,可能包含tpyos

如何基于一些编译时常量定义不同的类型,而不进行模板专门化

这是:

constexpr auto osPropsCreate()
{
    if constexpr (os == OS::Linux) {
        struct Props { const char* name; int props1; using handle = int; }; 
        return Props{"linux", 3};
    } else if constexpr (os == OS::MacOs) {
        struct Props { const char* name; using handle = float; }; 
        return Props{"mac"};
    } else if constexpr (os == OS::MsWindows) {
        struct Props { const char* name; using handle = int; }; 
        return Props{"win"};
    } else
        return;  
}

using OsProps = decltype(osPropsCreate());
constexpr OsProps osProps = osPropsCreate();
如您所见-我使用了新的构造
if constexpr
从一些“实现”函数生成依赖于编译时常量的类型。如果在D语言中使用
,那么它不像静态的
那么容易使用-但是它可以工作-我可以做到:

int linuxSpecific[osProps.props1];
int main() {
    std::cout << osProps.name << std::endl;
    OsProps::handle systemSpecificHandle;
}
int-linuxSpecific[osProps.props1];
int main(){

如果您只想更改初始值设定项,请将其放入(可能
constexpr
)函数。如果你想做更复杂的事情,那只是旧有的
static If
方案,它已付之一炬。在这种情况下,你甚至不需要
constepr If
:在类范围和命名空间级别不允许使用控制语句/块。它与
constepr
无关。或者,为什么不使用se模板专门化?你知道为什么@T.C.“旧的静态if提案付之一炬”?这篇文档或多或少描述了它吗?@PiotrNycz:是的,这是一个相当不错的概述。“if constexpr”它本身并不是一个避免宏的工具——它帮助我们避免SFINAE和/或标记分派技巧,在自定义函数行为时编写更简单的代码。所以,委员会并没有朝着这个方向迈出另一步,这真的很遗憾:当我们想要有条件地定义一些宏时,允许我们避免类似的代码混淆类模板中的mber字段或基类。这是可能的(使用继承),但生成的代码非常糟糕,几乎无法维护。我希望他们在D中看到“static if”。你的第一句话真的没有抓住重点。我认为这一点的全部目的是避免专门化模板,而不是因为它是“令人讨厌”,但因为它可能(a)引起与其他专门化的冲突,(b)阻止您保持一切不变(至少您必须派生一个额外的类),以及(c)因为它甚至不可能在所有情况下(如部分专门化嵌套类)这很酷-看起来是个不错的起点。我还计划研究boost mpl、fusion和hana,以找到更通用的方法-我想“模仿”“编译过程中的预处理器-具有不同的函数、类型-而不仅仅是值。一条注释:为什么不使用
std::bool_常量
而不是
bool_t
?@PiotrNycz,因为我不习惯使用
std::bool_常量
。您想要的版本是,“基本上与至少两个主要实现所使用的模板模型不兼容”。发生这种情况的可能性与地狱里滚雪球的可能性差不多。”但由于这些都是捕获较少的lambda,我非常确定它们都可以转换为原始函数指针*“lambda对象可能是
constexpr
,但*lambda函数本身不是。你需要一个C++17功能,并用
constexpr
显式声明它们。但实际上,不需要间接寻址;只需在初始化变量时调用lambda并直接存储它。@nicolas with
如果constexprconst char* const osName = 
  dispatch(
    bool_k<os == OS::Linux>,
    bool_k<os == OS::MacOs>,
    bool_k<os == OS::MsWindows>
  )(
    "Linux",
    "MacOS",
    "MS Windows",
    "Unknown"
  );
constexpr auto osPropsCreate()
{
    if constexpr (os == OS::Linux) {
        struct Props { const char* name; int props1; using handle = int; }; 
        return Props{"linux", 3};
    } else if constexpr (os == OS::MacOs) {
        struct Props { const char* name; using handle = float; }; 
        return Props{"mac"};
    } else if constexpr (os == OS::MsWindows) {
        struct Props { const char* name; using handle = int; }; 
        return Props{"win"};
    } else
        return;  
}

using OsProps = decltype(osPropsCreate());
constexpr OsProps osProps = osPropsCreate();
int linuxSpecific[osProps.props1];
int main() {
    std::cout << osProps.name << std::endl;
    OsProps::handle systemSpecificHandle;
}
constexpr auto osGetNameCreate() {
    if constexpr (os == OS::Linux) {
        struct Definition {
            static constexpr auto getName() {
                return "linux";
            }
        };
        return Definition::getName;
    } else if constexpr (os == OS::MacOs) {
        // we might use lambda as well
        return [] { return "mac"; };
    } else if constexpr (os == OS::MsWindows) {
        struct Definition {
            static constexpr auto getName() {
                return "win";
            }
        };
    } else
        return;
}


constexpr auto osGetName = osGetNameCreate();

int main() {
    std::cout << osGetName() << std::endl;
}