gpt4 book ai didi

c++ - 重载函数以获取 true_type 或 false_type 参数与使用 if 检查?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:09:49 24 4
gpt4 key购买 nike

与使用一个 if 语句相比,重载方法/函数以采用 true_typefalse_type 参数有什么好处吗?我看到越来越多的代码使用带有 true_typefalse_type 参数的重载方法。

使用 if 语句的简短示例

void coutResult(bool match)
{
if (match)
cout << "Success." << endl;
else
cout << "Failure." << endl;
}

bool match = my_list.contains(my_value);
coutResult(match);

与使用重载函数相比:

void coutResult(true_type)
{
cout << "Success." << endl;
}

void coutResult(false_type)
{
cout << "Failure." << endl;
}

bool match = my_list.contains(my_value);
coutResult(match);

最佳答案

您的第二个示例代码无法编译,这是编译时重载解析运行时条件分支 之间“选择”哪个不同的症状要执行的代码。

  • “重载函数以获取 true_typefalse_type 参数”允许在编译时做出此选择,前提是该决定仅取决于类型和编译时常量.
  • 如果在运行时某些变量值已知时才能完成选择,则有必要“使用 if 检查”。

在您的示例中,bool match = my_list.contains(my_value)显然在运行程序之前是不知道的,所以不能使用重载。

但区别对于模板来说最为重要,选择不仅是“执行哪条路径”,而是“实例化和编译然后调用哪些代码” .来自您的 linked video 的代码而是本着这种精神:

考虑这个(错误的)代码(为了简洁省略了 #includestd:: ):

template<typename InIt>
typename iterator_traits<InIt>::difference_type
distance(InIt first, InIt last)
{
// Make code shorter
typedef typename iterator_traits<InIt>::difference_type Diff;
typedef typename iterator_traits<InIt>::iterator_category Tag;

// Choice
if (is_same<Tag, random_access_iterator_tag>::value)
{
return last - first;
}
else
{
Diff n = 0;
while (first != last) {
++first;
++n;
}
return n;
}
}

这里至少有两个问题:

  • 如果您尝试使用不是随机访问的迭代器调用它(例如 std::list<T>::iterator ),它实际上将编译失败(错误指向行 return last - first; )。编译器必须实例化和编译整个函数体,包括两者 ifelse分支(即使只执行一个分支),表达式 last - first对于非 RA 迭代器无效。
  • 即使编译了,我们也会在运行时(有相关的开销)进行测试,以测试我们可以在编译时尽快测试的条件,并编译不需要的代码部分。 (编译器可能能够优化它,但这就是概念。)

要修复它,您可以这样做:

// (assume needed declarations...)

template<typename InIt>
typename iterator_traits<InIt>::difference_type
distance(InIt first, InIt last)
{
// Make code shorter
typedef typename iterator_traits<InIt>::iterator_category Tag;

// Choice
return distanceImpl(first, last, is_same<Tag, random_access_iterator_tag>());
}

template<typename InIt>
typename iterator_traits<InIt>::difference_type
distanceImpl(InIt first, InIt last, true_type)
{
return last - first;
}

template<typename InIt>
typename iterator_traits<InIt>::difference_type
distanceImpl(InIt first, InIt last, false_type)
{
// Make code shorter
typedef typename iterator_traits<InIt>::difference_type Diff;

Diff n = 0;
while (first != last) {
++first;
++n;
}
return n;
}

或者(可能在这里)直接使用类型:

/* snip */
distance(InIt first, InIt last)
{
/* snip */
return distanceImpl(first, last, Tag());
}

/* snip */
distanceImpl(InIt first, InIt last, random_access_iterator_tag)
{
return last - first;
}

/* snip */
distanceImpl(InIt first, InIt last, input_iterator_tag)
{
/* snip */
Diff n = 0;
/* snip */
return n;
}

现在只有“正确的”distanceImpl将被实例化和调用(选择在编译时完成)。

之所以可行,是因为类型(例如 InItTag )在编译时已知,而 is_same<Tag, random_access_iterator_tag>::value也是在编译时已知的常量。编译器只能根据类型来决定调用哪个重载(即重载解析)。

注意:尽管“标签”是按值传递的,但它们仅用作"dispatch"的未命名、未使用的参数(未使用它们的值,仅使用它们的类型)并且编译器可以优化它们。

您还可以阅读来自 Scott Meyers 的 Effective C++, Third Edition第 47 项:使用特征类获取有关类型的信息 .

关于c++ - 重载函数以获取 true_type 或 false_type 参数与使用 if 检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17388583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com