gpt4 book ai didi

C++ 模板 - 使用 "std::is_same_v"而不是专门化并避免编译错误?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:37:40 41 4
gpt4 key购买 nike

我是模板的新手,我正在尝试使用它们以避免重复非常相似的功能。

在下面的例子中,我做了一个简单的小例子来展示我的问题。

特别是,我有两个 struct(“solo”和“duo”)。这些结构有一个共同的成员 (a),其中一个有一个特定的成员 (b)。

然后我有一个模板函数,它可以采用任一结构并打印成员 a... 我希望它能够仅在结构类型为“duo”时打印成员 b。

我的做法(使用 std::is_same_v)无法编译。我读到可以使用专门化来这样做,但是我想知道是否有更优雅的方法?因为那时我有失去模板优势的感觉……但可能我还没有得到模板的力量以及如何/为什么使用它们。

非常感谢您的帮助!

#include <iostream>
#include <string>
#include <type_traits>

struct solo{
int a;
};

struct duo : solo{
int b;
};

template<class T>
void function(T test){
std::cout<< std::to_string(test.a);
if(std::is_same<T, duo>::value) std::cout<< std::to_string(test.b);
}

int main()
{
solo testS;
testS.a = 1;

function(testS);
}

最佳答案

回答你关于模板的问题(虽然在这个特定的应用程序中,由于很多原因,它不是正确的解决方案):

它不像你写的那样工作的原因是模板实例化发生在编译时,唯一发生的事情是 std::is_same 的值为模板参数计算。因此,在 function<solo> 的代码中这条线

if(std::is_same<T, duo>::value) std::cout<< std::to_string(test.b);

就像

if(false) std::cout<< std::to_string(test.b);

因为没有成员 b 而无法编译在 test .

为了让它工作,你需要两个模板,并在实例化模板时使用 SFINAE 选择正确的模板(并且由于函数模板不能部分特化,你需要像下面这样写,这真是一种愚蠢的方式编写两个重载。或者您可以完全专门化模板,但那样您就不会使用 if_same )。

template<class T>
typename std::enable_if<!std::is_same<T, duo>::value, void>::type function(T test){
std::cout<< std::to_string(test.a);
}

template<class T>
typename std::enable_if<std::is_same<T, duo>::value, void>::type function(T test){
std::cout<< std::to_string(test.a);
std::cout<< std::to_string(test.b);
}

此外,请注意 is_same 查看变量的静态类型,因此如果您有 solo&duo对象,它仍然会选择 solo过载。

模板的一个不那么愚蠢的用法是编写一个函数模板,它可以处理任何类型,它有一个成员int b。 .这使用了一个辅助元函数(一个结构,所以我们可以使用部分特化):

template <class T, class = int>
struct has_member_b : std::false_type {};

template <class T>
struct has_member_b<T, decltype(std::declval<T>().b)> : std::true_type {};

template<class T>
typename std::enable_if<has_member_b<T>::value, void>::type function(T test){
std::cout<< std::to_string(test.a);
std::cout<< std::to_string(test.b);
}

template<class T>
typename std::enable_if<!has_member_b<T>::value, void>::type function(T test) {
std::cout<< std::to_string(test.a);
}

(请注意,两个版本都假设有一个成员 a ,否则将无法编译)

关于C++ 模板 - 使用 "std::is_same_v"而不是专门化并避免编译错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50605907/

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