簡體   English   中英

具有約束類型的C ++中的可變參數函數添加

[英]Variadic functions addition in c++ with constrained types

我的目標是簡單添加任意數量的參數,只要它們具有以下類型-

  1. 整數(例如123)

  2. 表示為整數的字符串(例如“ 123”)

如果它們是其他類型,我將忽略它們。

途徑

  1. 我正在使用可變參數函數方法。
  2. 在函數中,我檢查類型。 如果類型是int ,那么我遞歸添加。 否則,我將忽略該論點,並繼續討論其他論點。

我認為代碼如下所示-

// BASE
template <typename T>
int func(T t)
{
    string type= typeid(t).name();
    if (type==typeid(int).name())
        return stoi(t);
    else if (type==typeid(const char*).name())
        return atoi(t);
    else
        return 0;
}
// RECUR
template<typename T, typename... Args>
int func(T t, Args... args) // recursive variadic function
{
    string type = typeid(t).name();
    if (type==typeid(int).name()){
        int sum = t;
        return sum+func(args...);
    }
    else
        return func(args...);

}

// MAIN
int main()
{
    // All testing here in MAIN.


    // [2]
    int funcres = func('a',1, 2.5000,"123");
    cout << funcres << endl;

    return 0;
}

這給了我預期的答案: 124。

但是,我做了以下觀察,發現我的代碼不是故障安全的。

  • 為什么在此基本功能行中需要stoi?

    如果(type == typeid(int).name())返回stoi(t);

如果我不這樣做,只調用return t ,則在調用函數時會出錯。

Cannot initialize return object of type 'int' with an lvalue of type 'const char *'

當我已經指定如果類型為整數時返回整數,這對我來說就沒有意義。

  • 即使我確實return stoi(t) (首先我也不明白為什么需要這樣做),並且如果類型為const char*return atoi(t) ,然后在開頭插入“ japan”或“ 123”或模板arg列表的中間 [例如, func(1,2,2.5000,"123",12); ]使代碼此時抱怨。

    int sum = t;

錯誤與上面相同。

Cannot initialize return object of type 'int' with an lvalue of type 'const char *'
  • 使用變參函數是最好的方法還是有替代方法?
  • 如果這是最好的方法(在我看來是如此,因為我需要考慮添加任意數量的參數和任何類型的參數),我在做什么錯?

C ++模板是靜態解析的,這意味着替換參數必須適用於所有替換,即使是在運行時無法訪問的替換也是如此。 但是,通過使用帶有幫助函數的重載而不是RTTI,我們可以更清晰地處理轉換:

template<class T>
int forceInt(T arg) { return 0; }

int forceInt(int arg) { return arg; }

int forceInt(std::string arg) { return std::stoi(arg); }

int forceInt(const char * arg) { return std::stoi(arg); }

使用此輔助函數,您可以執行簡單的遞歸求和:

int func() { return 0; }

template<typename T, typename... Args>
int func(T t, Args... args) // recursive variadic function
{

        return forceInt(t) + func(args...);
}

也可以擴展為處理任何整數類型。 通過在常規重載上使用SFINAE將其限制為非整數類型,這將使​​int重載成為整數類型的首選。 但是char是不可或缺的,因此如果您不希望將其隱式轉換為int,我們還需要添加一個char重載0:

template<class T, class U = typename std::enable_if<!std::is_integral<T>::value>::type>
int forceInt(T arg) { return 0; }

int forceInt(char arg) {return 0;}

超載是一種可能性。 您也可以使用一些模板魔術來做到這一點。 這樣做的好處是,在編譯時會從所有不兼容的類型中修剪要累加的列表(最后一個元素除外,如果最后一個元素不匹配,則將其替換為0)。

#include <cassert>
#include <string>
#include <type_traits>


template < typename T >
struct is_const_char : std::false_type {};
template < >
struct is_const_char < const char * > : std::true_type {};

template < typename T >
struct is_int : std::false_type {};
template < >
struct is_int < int > : std::true_type {};


// Break condition
template < typename T >
typename std::enable_if<is_int<T>::value, int>::type
sum(T t)
{
  return t;
}

template < typename T >
typename std::enable_if<is_const_char<T>::value, int>::type
sum(T t)
{
  return std::stoi(t);
}

template < typename T >
typename std::enable_if<!is_int<T>::value && !is_const_char<T>::value, int>::type
sum(T)
{
  return 0;
}


// Forward declarations
template < typename T, typename ... Args >
typename std::enable_if<is_const_char<T>::value, int>::type
sum(T, Args ...);

template < typename T, typename ... Args >
typename std::enable_if<is_int<T>::value, int>::type
sum(T, Args ...);

// Recursions
template < typename T, typename ... Args >
typename std::enable_if<!is_int<T>::value && !is_const_char<T>::value, int>::type
sum(T, Args ... args)
{
  return sum(args...);
}

template < typename T, typename ... Args >
typename std::enable_if<is_int<T>::value, int>::type
sum(T t, Args ... args)
{
  return t + sum(args...);
}

template < typename T, typename ... Args >
typename std::enable_if<is_const_char<T>::value, int>::type
sum(T t, Args ... args)
{
  return std::stoi(t) + sum(args...);
}


// Test it
int main()
{
  assert( sum('a', 1, 2, 3, "123", 4, 5) == 138 );
  assert( sum('a',1, 2.5000,"123") == 124 );
}

暫無
暫無

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

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