2017-05-08 8 views
0

構造体メンバの型に基づいてマクロを使用して関数を定義する必要があります。C++テンプレート型減算:Tをconstに変換する方法T

例:

struct A { 
    uint32_t value; // need to define a function return uint32_t 
    uint8_t str[0]; // need to define a function returning const uint8_t * 
}; 

私は次の関数を定義する必要があります -

uint32_t fun() {...} 
const uint8_t *fun() {...} << note the pointer types needs a const 

最初の試行:

使用のstd ::使用することへのポインタを配列型を減衰するdecay_t戻り値の型:std::decay_t<decltype(A::str)> fun() {...}

しかし、これは動作しません上記のような非標準の0の長さの配列。私は政治的な理由から構造体の定義を変更することはできません。だから私はゼロの長さの配列で生きなければならない。

第二の試み: 以下のように戻り値の型を推論:

template<class T> 
struct decay_zero { using type = std::decay_t<T>; }; 

template<class T> 
struct decay_zero<T[]> { using type = const T *; }; 

template<class T, size_t N> 
struct decay_zero<T[N]> { using type = const T *; }; // adding const to pointer type 

template<class T> 
struct decay_zero<T[0]> { using type = const T *; }; 

template<class T> 
struct return_type { 
private: 
     using U = typename std::remove_reference<T>::type; 
public: 
     using type = decay_zero<U>::type; 
}; 

return_type<decltype(A::str)>::type fun {...} 

をこれはGCCで動作しますが、何らかの理由でCLANGでは動作しません。 CLANGは、戻り型が長さが0の配列の配列であると不平を言っています。どうして?

3回目の試み:

だから私の3回目の試みはこれです - として、以下の「崩壊」関数を宣言します。私はポインタ型

template < 
      typename T, 
      typename std::enable_if_t<std::is_pointer<T>::value>* = nullptr 
     > 
const T __decayFunction (const T t) // making it const T 
{ 
    return return t; 
} 

template < 
      typename T, 
      typename std::enable_if_t<!std::is_pointer<T>::value>* = nullptr 
     > 
decltype(auto) __decayFunction (T t) 
{ 
    return t; 
} 

template<class T> 
struct return_type { 
private: 
     using U = typename std::remove_reference<T>::type; 
public: 
     using type = decltype(__decayFunction(std::declval<U>())); 
}; 

return_type<decltype(A::str)>::type fun() { ... } 

に 「ポーラ」追加できるように、私はポインタ型と非ポインタ型に別々の定義を持っているしかし、私は上記の関数の戻り値の型がconstのではないことがわかります。

constを作成するには?

+0

大きさゼロの配列が –

+0

C++で許可されていませんが、私は知っているが、それはGCCとCLANG拡張機能であり、私はそれを生きている - それは、レガシーコードの一部であるとして。 – MGH

+0

CLANG(またはCLang)ではなく、[Clang](http://clang.llvm.org/)です。 –

答えて

0

次の作品 -

template <typename T> 
const T *as_const_ptr (const T *p) 
{ 
    return p; 
} 

template < 
      typename T, 
      typename std::enable_if_t<std::is_pointer<T>::value>* = nullptr 
     > 
auto __decayFunction (T t) -> decltype(as_const_ptr(t)) { return as_const_ptr(t); } 

template < 
      typename T, 
      typename std::enable_if_t<!std::is_pointer<T>::value>* = nullptr 
     > 
decltype(auto) __decayFunction (T t) { return t; } 

template<class T> 
struct return_type { 
private: 
     using U = typename std::remove_reference<T>::type; 
public: 
     using type = decltype(__decayFunction(std::declval<U>())); 
}; 
+0

ではありませんが、それはなぜ機能しますか? –

+0

わかりません。したがって、私は答えを受け入れていません:-)私はテンプレートの専門家が説明するのを待っています。関数引数として渡されたときのTは、ポインタ型として導出されます。だからw/char a [10]、Tはchar *になり、何とかconstを加えることは無視されます。関数シグニチャがT * 'テンプレート const T * __decayFunction(const T * t){return t; } ' – MGH

関連する問題