2015-09-28 3 views
1

В следующем коде:троичный оператор с станд :: index_sequence

#include <iostream> 
#include <utility> 
#include <set> 

template <typename... Args> 
void f(Args... args) { 
    std::cout << sizeof...(Args) << " elements.\n"; 
} 

template <std::size_t... Is> 
void g (std::index_sequence<Is...>, const std::set<int>& set) { 
    f((set.find(Is) == set.end() ? Is : 2*Is)...); 
} 

int main() { 
    g (std::make_index_sequence<10>{}, {1,3,7,8}); 
} 

Я хочу f((set.find(Is) == set.end() ? Is : 2*Is)...); использовать Is если set.find(Is) == set.end() но НИЧЕГО в противном случае (вместо 2*Is). Таким образом, количество переданных аргументов не является фиксированным. Как это сделать?

Редактировать: Извините, но я слишком упростил проблему. Приведенный ниже код отражает более истинную проблему:

#include <iostream> 
#include <utility> 
#include <tuple> 

template <typename... Args> 
void f(Args... args) { 
    std::cout << sizeof...(Args) << " elements.\n"; 
} 

struct NullObject {}; 

template <typename Tuple, std::size_t... Is> 
void g (std::index_sequence<Is...>, const Tuple& tuple) { 
    f ((std::get<Is>(tuple) != std::get<Is+1>(tuple) ? std::get<Is>(tuple) : NullObject{})...); 
} 

int main() { 
    g (std::make_index_sequence<8>{}, std::make_tuple(2,1.5,'a','a',true,5,5,false)); 
} 

выше не компилируется из-за смешанными типами, принятых тройным оператором, но я думаю, что вы можете увидеть мою идею здесь. Я хочу передать NOTHING, если условие std::get<Is>(tuple) != std::get<Is+1>(tuple), поэтому вместо этого передаю NullObject{}, а затем как-то попытаюсь удалить все NullObjects из аргументов f, чтобы получить истинные аргументы, переданные в f.

+2

Вы не можете, а не с выражением * trernary *. Почему бы не использовать оператор 'if'? Или вызовите функцию 'f' в тернарном выражении вместо использования тернарного выражения в вызове' f'. –

+0

Если вы можете заменить содержимое 'std :: set' по типу компиляции, вы можете сделать что-то вроде: [Demo] (https://ideone.com/ZBF92c) – Jarod42

+0

@ Jarod42 Извините, но я слишком упростил проблему, и я обновил вопрос. Я не уверен, что ваша техника все еще применяется или нет. – prestokeys

ответ

4

Вы не можете использовать для этого тернарный оператор, для которого требуется два выражения, которые имеют общий тип. Здесь нет кубиков. Я не знаю, как условно вернуть другой тип , основанный на сравнении времени исполнения.

Вы должны были бы условно переадресовать типа на другую функцию, путем введения только другую вспомогательную функцию, которая выстраивается Args... и простой if заявление:

template <size_t... Js> 
void fhelper (std::index_sequence<>, const std::set<int>& , std::index_sequence<Js...>) { 
    f(Js...); 
} 

template <std::size_t I, size_t... Is, size_t... Js> 
void fhelper (std::index_sequence<I, Is...>, const std::set<int>& set, std::index_sequence<Js...>) { 
    if (set.find(I) == set.end()) { 
     fhelper(std::index_sequence<Is...>{}, set, std::index_sequence<Js..., I>{}); 
    } 
    else { 
     fhelper(std::index_sequence<Is...>{}, set, std::index_sequence<Js...>{}); 
    } 
} 

int main() { 
    fhelper (std::make_index_sequence<10>{}, {1,3,7,8}, std::index_sequence<>{}); 
} 
+0

@ Barry Извините, но я слишком упростил проблему, и я обновил вопрос. Я не уверен, что ваша техника все еще применяется или нет. – prestokeys

+0

@prestokeys Уверен, что это так, просто позвоните 'f (std :: get (tuple) ...)' вместо этого, я полагаю. – Barry

+0

@ Barry Да, я попробовал это и разместил его в своем вопросе, но он не компилируется (индекс элемента tuple ошибки out bounds). Хотя я думаю, что это можно исправить. Обновление: исправлено. Благодарю. – prestokeys

0

Я просто хотел поделиться решение общей проблемы, которую я искал. Сделано возможным решением Барри по конкретной проблеме, описанной выше:

#include <iostream> 
#include <utility> 
#include <tuple> 

template <template <std::size_t, typename> class Check, typename F, size_t... Js, typename Tuple> 
void screenArguments (std::index_sequence<>, std::index_sequence<Js...>, const Tuple& tuple) { 
    F()(std::get<Js>(tuple)...); 
} 

template <template <std::size_t, typename> class Check, typename F, std::size_t I, size_t... Is, size_t... Js, typename Tuple> 
void screenArguments (std::index_sequence<I, Is...>, std::index_sequence<Js...>, const Tuple& tuple) { 
    if (Check<I, Tuple>::execute(tuple)) 
     screenArguments<Check, F>(std::index_sequence<Is...>{}, std::index_sequence<Js..., I>{}, tuple); 
    else 
     screenArguments<Check, F>(std::index_sequence<Is...>{}, std::index_sequence<Js...>{}, tuple); 
} 

template <template <std::size_t, typename> class Check, typename F, typename Tuple, std::size_t N = std::tuple_size<Tuple>::value> 
void passCertainArguments (const Tuple& tuple) { 
    screenArguments<Check, F> (std::make_index_sequence<N>{}, std::index_sequence<>{}, tuple); 
} 

// Testing 
#include <typeinfo> 

template <typename... Args> 
void foo (Args&&...) { 
    std::cout << sizeof...(Args) << " elements passed into foo.\n"; 
} 

struct Foo { 
    template <typename... Args> 
    void operator()(Args&&... args) { 
     foo(std::forward<Args>(args)...); 
    } 
}; 

template <typename... Args> 
void bar (Args&&...) { 
    std::cout << sizeof...(Args) << " elements passed into bar.\n"; 
} 

struct Bar { 
    template <typename... Args> 
    void operator()(Args&&... args) { 
     bar(std::forward<Args>(args)...); 
    } 
}; 

template <std::size_t N, typename Tuple> 
struct CheckArguments { 
    static bool execute (const Tuple& tuple) { 
     return std::get<N>(tuple) != std::get<N+1>(tuple); 
    } 
}; 

struct NullObject {}; 

template <std::size_t N, typename Tuple> 
struct CheckNotNullObject { 
    static bool execute (const Tuple& tuple) { 
     return typeid(std::get<N>(tuple)) != typeid(NullObject); 
    } 
}; 

template <typename F, typename... Args> 
void executeWithoutNullObject (Args&&... args) { 
    passCertainArguments<CheckNotNullObject, F> (std::forward_as_tuple(args...)); 
} 

template <typename F, typename... Args> 
void executeRemoveConsecutiveRepeatElements (Args&&... args) { 
    const auto tuple = std::forward_as_tuple(args...); 
    passCertainArguments<CheckArguments, F, decltype(tuple), sizeof...(Args) - 1> (tuple); 
} 

int main() { 
    executeWithoutNullObject<Foo> (3, 5, 'a', true, NullObject{}, 'b', 5.8, NullObject{}, NullObject{}, '!', 2); 
    // 8 elements passed into foo. (the 3 NullObjects are removed) 
    executeRemoveConsecutiveRepeatElements<Bar> (2, 1.5, 'a', 'a', true, 5, 5, false); 
    // 5 elements passed into bar. (the first 'a', the first 5, and 'false' removed) 
} 
Смежные вопросы