Использование шаблона для создания конструктора по умолчанию в C ++ в основном - PullRequest
0 голосов
/ 04 марта 2020

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

Если у меня есть класс:

myclass.h

class myClass
{
private:
    float a;
public:
    myClass(float _a) {a = _a;}
    float getA(){return a;}
    ~myClass() {}
};

Есть ли способ шаблона этого в вашем главном, например, так:

main. cpp

#include "myclass.h"

typedef myClass<5.0> Dummy

int main(int argc, char const *argv[])
{
    // EDIT: removed the following typo
    // Dummy dummy();
    Dummy dummy;
    std::cout << dummy.getA() << std::endl;
    return 0;
}

Который должен выводить:

> 5.0000000

Так что один может определить в основном стандартный способ построения экземпляров.

Ответы [ 4 ]

2 голосов
/ 04 марта 2020

C ++ 17 и ниже

К сожалению, C ++ пока не позволяет использовать типы с плавающей запятой в качестве нетиповых параметров шаблона. Тем не менее, вы можете подделать его, приняв числитель и знаменатель в качестве целых чисел, а затем выполняя эту «математику» в классе, чтобы получить значение с плавающей запятой. Это выглядело бы как

template<size_t numerator, size_t denominator = 1> // use a default value so you don't have to specify the denominator for whole values
class myClass
{
private:
    float a;
public:
    myClass(float _a = static_cast<float>(numerator) / denominator) : a(_a) {}
    float getA(){return a;}
    ~myClass() {}
};

typedef myClass<5> Dummy;

int main(int argc, char const *argv[])
{
    Dummy dummy; // notice this isn't Dummy dummy();.  That makes a function, not a variable
    std::cout << dummy.getA() << std::endl;
    return 0;
}

Вы также можете добавить значение по умолчанию к numerator, если хотите, чтобы вы могли сделать

// Pre C++17
myClass<> foo; 

//C++17 and later
myClass foo;

C ++ 20

Теперь, когда мы можем использовать типы с плавающей запятой 1 , код можно упростить до:

template<float default_value = 0.0f>
class myClass
{
private:
    float a;
public:
    myClass(float _a = default_value) : a(_a) {}
    float getA(){return a;}
    ~myClass() {}
};

typedef myClass<5.0f> Dummy;

int main(int argc, char const *argv[])
{
    Dummy dummy;
    std::cout << dummy.getA() << std::endl;
    return 0;
}

1: на самом деле это еще не поддерживается компиляторами, но это разрешено стандарт

1 голос
/ 04 марта 2020

Опираясь на ответ @ pptaszni , вы можете создать «фабричную фабричную функцию»:

auto makeMyClassFactory(float value) {
    return [=] {
        return myClass{value};
    };
}

auto const Dummy = makeMyClassFactory(5.0f);

int main(int argc, char const *argv[])
{
    auto dummy = Dummy();
    std::cout << dummy.getA() << std::endl;
    return 0;
}

Посмотреть это в прямом эфире на Wandbox

0 голосов
/ 04 марта 2020

Возможно, вам лучше использовать экземпляр по умолчанию, копии которого вы создаете всякий раз, когда вам нужен новый экземпляр:

#include "myclass.h"

Dummy myClass(5.0);

int main(int argc, char const *argv[])
{
    myClass dummy1 = Dummy;
    std::cout << dummy1.getA() << std::endl;
    myClass dummy2 = Dummy;
    std::cout << dummy2.getA() << std::endl;
    return 0;
}
0 голосов
/ 04 марта 2020

Не совсем, но вы можете написать фабричную функцию (или класс, если она более сложная), например:

myClass createMyClassV5()
{
  return myClass(5.0);
}

К сожалению, вы не можете сделать это шаблоном, потому что float не разрешены быть шаблонными нетиповыми параметрами. Вы можете сделать это с помощью int.

...