簡體   English   中英

如何改進采用編譯時已知條件的構造函數?

[英]How to improve a constructor that takes a compile-time-known condition?

我有一個看起來像這樣的構造函數:

SomeType(const bool condition = true) {
  if (condition) {
    // do some init
  } else {
    // do some other init
  }
}

但是由於在編譯時已知condition ,我懷疑這可以改進,避免傳遞變量並在運行時評估if語句。 這是真的? 怎么可能呢?

C ++中沒有語法來調用像這樣的簡單模板化構造函數

struct SomeType
{
    template <bool condition>
    SomeType();
};

template<>
SomeType::SomeType<true>()
{
    // do some init
}

template<>
SomeType::SomeType<false>()
{
    // do some other init
}

// ...

SomeType<true> st; // this syntax is used to create an object of a class template:

// template <bool>
// struct SomeType
// {
// };

一個眾所周知的解決方法是通過函數重載來模仿模板特化:

#include <type_traits>

struct SomeType
{
    SomeType(std::true_type)
    {
        // do some init
    }

    SomeType(std::false_type)
    {
        // do some other init
    }

    template <bool condition>
    static SomeType New()
    {
        return SomeType(std::integral_constant<bool, condition>{});
    }
};

使用示例:

auto st = SomeType::New<false>();

在這段代碼中,使用了來自type_traits頭的C ++ 11 std::integral_constant模板類,但它足以在C ++ 03中編寫類似的類模板。

現場演示

如果條件始終是編譯時常量,則可以執行以下操作:

class SomeType
{
    void initTrue() {}
    void initFalse() {}
public:
    template <bool C>
    struct Discrim {}
    SomeType( Discrim<true> ) { initTrue(); }
    SomeType( Discrim<false> ) { initFalse(); }
};

然后你必須用以下方法調用它:

SomeType((SomeType::Discrim<condition>()));

或者您可以簡單地定義兩個枚舉,您可以在其上重載構造函數:

class SomeType
{
    void initTrue() {}
    void initFalse() {}
public:
    enum ConditionTrue { conditionTrue };
    enum ConditionFalse { conditionFalse };
    SomeType( ConditionTrue ) { initTrue(); }
    SomeType( ConditionFalse ) { initFalse(); }
};

或者你可以做你正在做的事情; 額外測試不太可能為運行時間增加可測量的差異。 如果確實如此(如分析器所示),它只能是構造函數足夠小以便內聯(在這種情況下,優化器中的常量傳播將確保沒有實際的if )。 上述技術通常僅在您需要具有明顯不同的初始化列表的單獨構造函數時才有用。

如果您不信任編譯器,那么您(也許)可以將您的類的構造函數作為模板:

template< bool condition >
SomeType();

template<>
SomeType< true >() {
    // do some init
}
template<>
SomeType< false >() {
    // do some other init
}

編輯:作為@Constructor(名稱說明一切)))說你不能調用這種類型的構造函數。 因此,您可以在函數中移動所有初始化。 像這樣:

struct SomeType {
    template< bool condition >
    void init();
};
template<>
void SomeType::init< true >() {
  // do some init
}
template<>
void SomeType::init< false >() {
  // do some other init
}

SomeType t;
t.init< true >();
SomeType f;
f.init< false >();

http://ideone.com/3CJS41

暫無
暫無

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

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