我正在將一個用 C 17 撰寫的專案降級到 C 14。在降級時,我遇到了一段代碼if constexpr,我希望將其轉換為 C 14(據我所知,if constexpr這是 C 17 的功能)。
Boostis_detected用于檢查給定型別是否具有星號運算子或 get 方法。
#include <iostream>
#include <boost/type_traits/is_detected.hpp>
#include <type_traits>
#include <boost/optional/optional.hpp>
#include <memory>
#include <typeinfo>
template < template < typename... > typename Operation, typename... Args >
constexpr bool is_detected_v = boost::is_detected< Operation, Args... >::value;
template < typename T >
using has_star_operator = decltype( *std::declval< T >( ) );
template < typename T >
using has_get_method = decltype( std::declval< T >( ).get( ) );
有一個函式呼叫deref用于取消參考指標、陣列、迭代器、智能指標等型別。
template < typename T >
inline constexpr const auto&
deref( const T& value )
{
if constexpr ( is_detected_v< has_star_operator, T > )
{
return deref( *value );
}
else if constexpr ( is_detected_v< has_get_method, T > )
{
return deref( value.get( ) );
}
else
{
return value;
}
}
if constexpr我嘗試在不使用以下方法的情況下形成解決方案std::enable_if:
template <typename T>
typename std::enable_if<
!is_detected_v<has_get_method, T> && is_detected_v<has_star_operator, T>,
decltype( *std::declval< const T >( ) )>::type
deref(const T& value)
{
std::cout << "STAR " << typeid(*value).name() << std::endl;
return *value;
}
template <typename T>
typename std::enable_if<
is_detected_v<has_get_method, T>,
decltype( std::declval< const T >( ).get( ) ) >::type
deref(const T& value)
{
std::cout << "GET " << typeid(value.get()).name() << std::endl;
return value.get();
}
template <typename T>
typename std::enable_if<
!is_detected_v<has_get_method, T> && !is_detected_v<has_star_operator, T>,
const T>::type
deref(const T& value)
{
std::cout << "NONE\n";
return value;
}
int main()
{
int VALUE = 42;
boost::optional<int> optional_value = boost::make_optional(VALUE);
int a = 42;
int *b = &a;
const int array[ 4 ] = {VALUE, 0, 0, 0};
//const auto list = {std::make_unique< int >( VALUE ), std::make_unique< int >( 0 ),
// std::make_unique< int >( 0 )};
//const auto iterator = list.begin( );
//std::unique_ptr<int> u = std::make_unique< int >( VALUE );
std::cout << deref(a) << std::endl;
std::cout << deref(optional_value) << std::endl;
std::cout << deref(b) << std::endl;
std::cout << deref(array) << std::endl;
//std::cout << deref(iterator) << std::endl;
//std::cout << deref(u) << std::endl;
}
但是,對于必須進行多次取消參考的迭代器和智能指標等情況,上述方法失敗了。例如,對于 a std::unique_ptr, firstp.get()將被稱為 ( auto q = p.get()),然后是星號運算子 ( *q)。
我是模板的初學者,需要一些幫助。請讓我知道如何解決這個問題。
我正在使用 GCC 5.4 進行編譯。
uj5u.com熱心網友回復:
利用標簽調度的解決方案怎么樣?
這個想法是將代碼從您的分支移動到三個輔助函式。這些函式在最后一個引數上多載,其唯一目的是允許您稍后呼叫正確的引數:
template <typename T>
constexpr const auto& deref(const T& value);
template <typename T>
constexpr const auto& deref(const T& value, std::integral_constant<int, 0>) {
return deref(*value);
}
template <typename T>
constexpr const auto& deref(const T& value, std::integral_constant<int, 1>) {
return deref(value.get());
}
template <typename T>
constexpr const auto& deref(const T& value, std::integral_constant<int, 2>) {
return value;
}
template <typename T>
constexpr const auto& deref(const T& value) {
using dispatch_t = std::integral_constant<
int, is_detected_v<has_star_operator, T>
? 0
: (is_detected_v<has_get_method, T> ? 1 : 2)>;
return deref(value, dispatch_t{});
}
通過上述實作,以下編譯:
int main() {
int VALUE = 42;
boost::optional<int> optional_value = boost::make_optional(VALUE);
int a = 42;
int* b = &a;
const int array[4] = {VALUE, 0, 0, 0};
const auto list = {std::make_unique<int>(VALUE),
std::make_unique<int>(0), std::make_unique<int>(0)};
const auto iterator = list.begin();
std::unique_ptr<int> u = std::make_unique<int>(VALUE);
std::cout << deref(a) << std::endl;
std::cout << deref(optional_value) << std::endl;
std::cout << deref(b) << std::endl;
std::cout << deref(array) << std::endl;
std::cout << deref(iterator) << std::endl;
std::cout << deref(u) << std::endl;
}
和輸出:
42
42
42
42
42
42
另請注意,在 C 14 之前,當宣告模板引數是模板本身時,語法為
template <template <typename...> class Operation, typename... Args>
// ^ class: you can use typename since C 17
constexpr bool is_detected_v = boost::is_detected<Operation, Args...>::value;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/478092.html
標籤:C 模板 促进 C 14 if-constexpr
