剛剛開始探索我的一項任務的模板功能,我需要根據模板中的型別名稱添加一些操作。有人能指出這種結構有什么問題嗎:
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T>
T foo()
{
if(std::is_same<T, int>::value)
{
return 2;
}
if(std::is_same<T, std::string>::value)
{
return "apple";
}
}
int main()
{
std::cout<<"foo is: "<<foo<int>()<<std::endl;
return 0;
}
我想知道:
- 為什么會發生此錯誤
main.cpp:23:16: error: invalid conversion from ‘const char*’ to ‘int’以及如何擺脫它? - 有沒有更好的方法可以根據提供給函式的內容執行特定操作
typename?
更新:
原來我的程式使用的是低于 C 17 的編譯器
試圖:
我嘗試了另一種方法來處理這種情況,但失敗了:
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T, typename U>
T foo()
{
T t = U;
return t;
}
int main()
{
std::cout<<"foo is: "<<foo<int, 1>()<<std::endl;
return 0;
}
任何人都可以指出這里出了什么問題?
uj5u.com熱心網友回復:
問題是,即使您T是int,所有分支仍然必須編譯。因此第二個 return 陳述句會導致錯誤,因為字串文字無法轉換為int回傳值。
從 C 17 開始,您可以使用if constexpr來告訴編譯器條件是一個編譯時常量,它允許它只編譯所需的分支:
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T>
T foo()
{
if constexpr(std::is_same<T, int>::value)
{
return 2;
}
if constexpr(std::is_same<T, std::string>::value)
{
return "apple";
}
}
int main()
{
std::cout<<"foo is: "<<foo<int>()<<std::endl;
return 0;
}
如果您需要早期標準中的解決方案,則必須使用如下模板專業化:
#include <iostream>
#include <type_traits>
using namespace std;
//general template
template <typename T>
T foo();
//specialization for int
template <>
int foo<int>()
{
return 2;
}
//specialization for string
template <>
string foo<string>()
{
return "apple";
}
int main()
{
std::cout<<"foo is: "<<foo<int>()<<std::endl;
return 0;
}
uj5u.com熱心網友回復:
模板實體化必須在所有分支上都有效,而您的卻不是。我的意思是這就是模板生成的函式的樣子:
int foo<int>()
{
if(true)
{
return 2;
}
if(false)
{
return "apple"; // error
}
}
std::string foo<std::string>()
{
if(false)
{
return 2; // error
}
if(true)
{
return "apple";
}
}
從 C 17 開始,你可以使用 constexpr if 來解決這個問題:
template <typename T>
T foo()
{
if constexpr (std::is_same<T, int>::value)
{
return 2;
}
else if constexpr (std::is_same<T, std::string>::value)
{
return "apple";
}
}
uj5u.com熱心網友回復:
如果您使用的是較早的語言版本,則 C 17 的 constexpr-if 的另一種替代方法是標記調度:
#include <iostream>
#include <string>
#include <type_traits>
namespace detail {
template <typename T> struct Tag {};
int f_impl(Tag<int>) { return 2; }
std::string f_impl(Tag<std::string>) { return "apple"; }
} // namespace detail
template <typename T> T foo() { return detail::f_impl(detail::Tag<T>{}); }
int main() {
std::cout << "foo is: " << foo<int>() << std::endl;
return 0;
}
對于這個簡單的例子,專業化就可以了,但是標簽調度對于更復雜的“if-else-dispatch”邏輯很有用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/390180.html
