簡體   English   中英

沒有默認功能的C ++模板專業化

[英]C++ template specialization without default function

我有以下編譯和運行良好的代碼:

template<typename T>
T GetGlobal(const char *name);

template<>
int GetGlobal<int>(const char *name);

template<>
double GetGlobal<double>(const char *name);

但是我想刪除“默認”功能。 也就是說,我想對GetGlobal <t>進行所有調用,其中't'不是int或double錯誤。

例如,GetGlobal <char>()應該是編譯時錯誤。

我試圖刪除默認函數,但是,正如我想象的那樣,我收到了很多錯誤。那么有沒有辦法“禁用”它並允許只調用函數的專用版本?

謝謝!

要獲得編譯時錯誤,請將其實現為:

template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined

如果你使用Boost,你可以使它更優雅:

template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }

C ++ Standard保證不存在sizeof等於0的類型,因此您將得到編譯時錯誤。

正如sbi在他的評論中所建議的那樣,最后可以減少到:

template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }

我更喜歡第一種解決方案,因為它提供了比其他解決方案更清晰的錯誤消息(至少在Visual C ++中)。

雖然這是一個陳舊且過時的問題,但值得注意的是C++11使用已刪除的函數解決了這個問題:

template<typename T>
T GetGlobal(const char *name) = delete;

template<>
int GetGlobal<int>(const char *name);

UPDATE

這不會在MacOS llvm 8下編譯。 這是由於一個仍然懸掛4年的缺陷(見這個錯誤報告 )。

以下解決方法將適合該問題(使用static_assert構造)。

template<typename T>
T GetGlobal(const char *name) {
    static_assert(sizeof(T) == 0, "Only specializations of GetGlobal can be used");
}

template<>
int GetGlobal<int>(const char *name);

UPDATE

Visual Studio 15.9有同樣的bug。 使用以前的解決方法。

如果你沒有實現它,你至少會得到一個鏈接器錯誤。 如果您想要編譯時錯誤,可以使用類模板執行此操作:

template<typename T>
struct GlobalGetter;

template<>
struct GlobalGetter<int> {
  static int GetGlobal(const char *name);
};

template<>
struct GlobalGetter<double> {
  static double GetGlobal(const char *name);
};

template<typename T>
T GetGlobal(const char *name)
{
  return GlobalGetter<T>::GetGlobal(name);
}

我建議不要實際提供一個實現,只是一個方法的聲明。

另一種選擇是使用編譯時斷言。 Boost有很多這樣的野獸。

namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
                            boost::same_type<T, int> >));

還有它的消息版本對應,這將有所幫助。

以下是使用boost的替代技術:

將typedef聲明為依賴名稱

這是有效的,因為DONT的名稱查找僅在替換'T'時發生。 這是Kirill給出的示例的類似(但合法)版本

template <typename T>
T GetGlobal (const char * name) {
    typedef typename T::DONT CALL_THIS_FUNCTION;
}

使用不完整的返回類型

此技術不適用於專業化,但它適用於重載。 這個想法是聲明一個返回不完整類型但不調用它的函數的合法性:

template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM