Разрешение параметра шаблона быть только определенными типами и принятие решения на его основе

Самый простой способ - использовать класс Scanner в Java и объект FileReader. Простой пример:

Scanner in = new Scanner(new FileReader("filename.txt"));

Scanner имеет несколько методов для чтения в строках, числах и т. Д. Вы можете найти дополнительную информацию об этом на странице документации Java.

Например, прочитав весь контент в String:

StringBuilder sb = new StringBuilder();
while(in.hasNext()) {
    sb.append(in.next());
}
in.close();
outString = sb.toString();

Также, если вам нужна конкретная кодировка, вы можете использовать это вместо FileReader:

new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)
5
задан Darlyn 15 January 2019 в 18:30
поделиться

3 ответа

без перегрузки

, но перегрузка здесь делает код простым:

template<typename ... Ts>
void doSomething(MyClass_one, Ts...two){
    cout << "im one" << endl;
}

template<typename ... Ts>
void doSomething(MyClass_two, Ts...two){
    cout <<"im two" << endl;
}
0
ответ дан Jarod42 15 January 2019 в 18:30
поделиться

Если вы можете использовать C ++ 17, вы можете использовать if constexpr:

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
  if constexpr ( isOne<T>::value ) { cout << "im one" << endl;}
  else if constexpr ( isTwo<T>::value){ cout <<"im two" << endl;}
}

Конечно, isOne<T>::value и isTwo<T>::value должны быть static constexpr переменными.

Если вы хотите проверить типы первого аргумента функции, применяется тот же подход, только нет необходимости что-то вроде isOne и isTwo, вы можете использовать std::is_same_v, чтобы увидеть, если первый аргумент - MyClassOne или MyClassTwo:

#include <iostream> 
#include <type_traits>
#include <vector> 

class MyClassOne {}; 
class MyClassTwo {}; 

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
  if constexpr ( std::is_same_v<T, MyClassOne> ) 
    std::cout << "im one" << std::endl;
  else if constexpr ( std::is_same_v<T, MyClassTwo> )
    std::cout <<"im two" << std::endl;
  else
    static_assert(false, "Only MyClassOne and MyClassTwo are permitted first arguments.");
}
int                                                                                                                                         
main(int argc, char **argv) { 

    MyClassOne one; 
    MyClassTwo two; 

    doSomething(one, 1.5, two); 
    doSomething(two, 'c', one);

    std::vector<MyClassOne> onesVector;
    doSomething(onesVector, 1.0); 

}  

std::is_same_v<A,B> приводит к значению true, если типы A и B совпадают. Это отвечает на ваш вопрос: «если параметром один является MyClass_one, он должен вывести« im one », если его MyClass_two должен вывести« im two ».», И завершается неудачно во время компиляции, если первый аргумент имеет тип, отличный от etither myClassOne или [ 1116]. [1 123]

Редактировать : добавлен static_assert, который гарантирует, что компиляция завершится неудачно, если первым аргументом будет что-то еще, кроме MyClassOne или MyClassTwo, как это было предложено Джастином Таймом в комментарии.

0
ответ дан tmaric 15 January 2019 в 18:30
поделиться

Я бы предложил разделить вашу функцию на две части. Оставьте итеративную часть doSomething и выделите то, что вы хотите сделать.

template<typename T> void theThing(T one);

template<>
void theThing<MyClass_one>(MyClass_one one) {
    cout << "im one" << endl;
}

template<>
void theThing<MyClass_two>(MyClass_two one) {
    cout << "im two" << endl;
}

template<typename T, typename ... Ts>
void doSomething(T one, Ts...two) {
    theThing(one);
}

Таким образом, вы можете иметь специализированные вещи для каждого класса, который вы хотите использовать. Бонус, он не будет компилироваться для типов, для которых theThing не специализируется.

0
ответ дан ZeroUltimax 15 January 2019 в 18:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: