Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/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_C++17 - Fatal编程技术网

C++ 基于布尔模板参数的可选参数

C++ 基于布尔模板参数的可选参数,c++,templates,c++17,C++,Templates,C++17,我正试图声明一个模板函数,它 如果模板布尔值为true,则有3个参数 如果模板布尔值为false,则只有2个参数 这可能吗 下面的代码可以编译,但是两个版本都需要3个参数。当模板布尔值为false时,我需要它只需要2个参数,并且函数的结果用法-用户只需要提供2个参数 理想情况下,这是一个单一的函数,因此可以避免代码重复,因为函数定义非常简单 静态: 遍历区域,对节点应用哈希 动态: 遍历区域,通过2D旋转变换节点,对节点应用哈希 理想情况下,要使用的逻辑的选择也可以在编译时进行评估 如果co

我正试图声明一个模板函数,它

  • 如果模板布尔值为true,则有3个参数
  • 如果模板布尔值为false,则只有2个参数
这可能吗

下面的代码可以编译,但是两个版本都需要3个参数。当模板布尔值为false时,我需要它只需要2个参数,并且函数的结果用法-用户只需要提供2个参数

理想情况下,这是一个单一的函数,因此可以避免代码重复,因为函数定义非常简单

静态: 遍历区域,对节点应用哈希

动态: 遍历区域,通过2D旋转变换节点,对节点应用哈希

理想情况下,要使用的逻辑的选择也可以在编译时进行评估

如果constexpr(动态)

模板
void setHashAt(rect2D\u t区域,uint32\u t常量散列,std::conditional\u t vR)

谢谢

当然,你可以通过SFINAE做到这一点

#include <type_traits>

template <const bool EnableThird, std::enable_if_t<EnableThird, int> = 0>
void dynamic_parameter_count(int one, int two, int three) {
    std::cout << "EnableThird was true\n";
}

template <const bool EnableThird, std::enable_if_t<!EnableThird, int> = 0>
void dynamic_parameter_count(int one, int two) {
    std::cout << "EnableThird was false\n";
}
#包括
模板
无效动态参数计数(整数1、整数2、整数3){
标准::cout
然后,您可以简单地使用调用

dynamic_parameter_count<true>(1, 2, 3);
dynamic_parameter_count<false>(1, 2);
动态参数计数(1,2,3);
动态参数计数(1,2);
这是通过基于模板参数启用或禁用其中一个模板实例化来实现的。事实上,据我所知,您确实需要两个模板来实现这一点。我不确定您是否可以在一个模板中实现这一点

但是,您也可以简单地为同一个函数指定两个版本

void parameter_count(int one, int two, int three) {
    std::cout << "3 Parameters\n";
}

void parameter_count(int one, int two) {
    std::cout << "2 Parameters\n";
}
void参数_计数(整数一、整数二、整数三){

std::cout这是您的解决方案的一个小变化

#include <type_traits>

struct None{};

template<bool select>
void foo(int, std::conditional_t<select, int, None> = None{}) {
}

int main() {
    foo<false>(1);
    foo<true>(1,2);
    // foo<false>(1,2); // fails
    // foo<true>(1); // fails
}
#包括
结构无{};
模板
void foo(int,std::conditional_t=None{}){
}
int main(){
傅(1),;
foo(1,2);
//foo(1,2);//失败
//foo(1);//失败
}

我不认为这是一个干净的解决方案,但相反,重载和重构代码以避免重复应该是正确的方法(如评论中所建议)。

简单重载似乎更简单,但要直接回答您的问题,您可以(ab)使用可变模板和SFINAE:

template<bool Dynamic,
         typename ... Ts,
         std::enable_if_t<(Dynamic == false && sizeof...(Ts) == 0)
                          || (Dynamic == true && sizeof...(Ts) == 1
                              && std::is_convertible_v<std::tuple_element_t<0, std::tuple<Ts...>>,
                                                      v2_rotation_t>)
                         , bool> = false>
void setHashAt(rect2D_t area, uint32_t const hash, const Ts&...   vR);
模板
void setHashAt(rect2D_t区域、uint32_t常量散列、常量Ts和…vR);

需要注意的是,第三个参数应该是可推断的(因此没有
{..}
).

模板参数是否仅用于选择参数的数量?询问,因为对于不同数量的参数,您只需要两个重载,不需要模板是的,在这种情况下,我想定义一个函数,而不是两个。如果我重载了函数的内容,这将是一个复制和粘贴作业。如果我拥有所有这些内容,那将非常好n一,因为它们非常相似。不,不需要复制。参数较少的是
void foo(第一,第二){具有所有参数的实际函数(第一,第二);}
。如果实际函数可以为缺少的函数设置默认值,而没有此函数的某些主体,则很难解释为什么您认为简单重载是一个糟糕的解决方案。抱歉,但我认为您没有理解。两个重载之间的差异不得超过最小值。您可以编写两个重载,并且唯一的代码是duplicated是这两个函数的不同之处,即实际上它是不重复的,这非常简单。不幸的是,它仍然需要分为两个函数。@J.Tully请看我的编辑,也许可选的变体可能适合您。“肉”在这两种情况下,函数的形式非常相似-唯一的区别是当前点的变换由可选参数迭代,这是一个旋转。啊,很好的选择!如果不可能执行此函数的编译时变体,这似乎是一种方式。谢谢!有趣-是的,我希望在那里使用void你有“None”,并且编译器足够聪明,可以从函数参数中删除它。不。这是一个有趣的选择。
foo(1,{})
是可能的。(这可能会有问题,因为
foo(1,{})
是正确的)。同意。可以通过禁用默认/聚合初始化进行简单的修复,但最终我们都同意正确的解决方案似乎是正常的重载…有趣的方法!
#include <type_traits>

struct None{};

template<bool select>
void foo(int, std::conditional_t<select, int, None> = None{}) {
}

int main() {
    foo<false>(1);
    foo<true>(1,2);
    // foo<false>(1,2); // fails
    // foo<true>(1); // fails
}
template<bool Dynamic,
         typename ... Ts,
         std::enable_if_t<(Dynamic == false && sizeof...(Ts) == 0)
                          || (Dynamic == true && sizeof...(Ts) == 1
                              && std::is_convertible_v<std::tuple_element_t<0, std::tuple<Ts...>>,
                                                      v2_rotation_t>)
                         , bool> = false>
void setHashAt(rect2D_t area, uint32_t const hash, const Ts&...   vR);