Как я могу запретить моему шаблонному конструктору принимать класс в качестве параметра при передаче объекта в функцию - PullRequest
4 голосов
/ 13 марта 2020

У меня есть класс с шаблонным конструктором, который инициализирует массив, но когда я передаю свой инициализированный объект в функцию, функция использует шаблонный конструктор для создания копии (это то, что я думаю).

Существует ли правильный синтаксис / способ предотвратить это?

Мой код, который определяет класс, функцию и основной код выполнения :

#include <stdio.h>
#include <array>

template<typename T, typename Args>
class myClass{

public:
    std::array<T, 10> data;

    template<typename ... Element>
    constexpr myClass(Element&&... input) : data{input...} {};

    myClass(const myClass& obj){
        data = obj.data;
    }
};

template<typename T, typename Args>
constexpr auto myFunction(myClass<T, Args> obj){
    return 0;
}

template<typename T, typename Args>
constexpr auto myFunction(myClass<T, Args>&& obj){
    return 0;
}

int main()
{
    myClass<double, std::tuple<int, int, double>> expr_obj;

    auto temp = expr_obj;//ERROR

    auto result = myFunction(expr_obj); //ERROR

    return 0;
}

сообщение об ошибке выглядит следующим образом:

main.cpp: In instantiation of ‘constexpr myClass<T, Args>::myClass(Element&& ...) [with Element = {myClass<double, std::tuple<int, int, double> >&}; T = double; Args = std::tuple<int, int, double>]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',43)">main.cpp:43:38</span>:   required from here
main.cpp:19:58: error: cannot convert ‘myClass >’ to ‘double’ in initialization
     constexpr myClass(Element&&... input) : data{input...} {};
                                                          ^

Я добавил сообщение об ошибке от CLion, поскольку оно предоставляет больше информации:

In instantiation of ‘constexpr myClass<T, Args>::myClass(Element&& ...) [with Element = {myClass<double, std::tuple<int, int, double> >&}; T = double; Args = std::tuple<int, int, double>]’:

cannot convert ‘myClass<double, std::tuple<int, int, double> >’ to ‘double’ in initialization
  304 |     constexpr myClass(Element&&... input) : data{input...} {};

Ответы [ 2 ]

4 голосов
/ 13 марта 2020

Один из способов сделать это - ограничить элементы Element типом T. Это будет выглядеть как

template<typename T, typename Args>
class myClass{

public:
    std::array<T, 10> data;

    template<typename ... Element, std::enable_if_t<(std::is_same_v<std::decay_t<Element>, T> && ...), bool> = true>
    //                             ^  this says only enable this template if all Element are T                ^
    constexpr myClass(Element&&... input) : data{input...} {};

    myClass(const myClass& obj){
        data = obj.data;
    }
};
1 голос
/ 13 марта 2020

Просто отметьте ваш шаблонный конструктор как explicit:

template <typename T, typename Args>
class myClass {
public:
    std::array<T, 10> data;

    template <typename... Element>
    explicit constexpr myClass(Element&&... input) : data{input...} {};

    myClass(const myClass&) = default;
};
...