无法将返回对象与SIFNE分离。

huangapple go评论85阅读模式
英文:

failed to separate return object with SIFNE

问题

I want to build a simple array data wrapper. It shows me a data what I suggested views (like double or character).

This function get_type() simply returns separate objects with enum tags (I used SIFNE).

So my expectation was, if some pointer (void* tmp) existed, when I call get_type<CHARACTER>(tmp, size) then function would return an arrayview<char> object.

But it isn't, it raises an error:

c2440 'function-style-cast' cannot convert from 'initializer list' to

This is my full code of my test code (I simplified my problem):

#include <iostream>

using namespace std;

enum class test_array_type {
    CHARACTER,
    DOUBLE
};

template<typename T>
class arrayview {
    // yeah, you might think that why this class is needed,
    // I removed many member methods.
public:
    T* m_data;
    const int m_size;
    arrayview(T* data, int size) :m_data(data), m_size(size) {};
};

template<test_array_type T>
struct testType {
    using type = typename arrayview<double>;
};

template<>
struct testType<test_array_type::CHARACTER> {
    using type = typename arrayview<char>;
};

template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
    switch (ty) {
        case test_array_type::CHARACTER:
            return testType<test_array_type::CHARACTER>::type(tmp, 10);
        case test_array_type::DOUBLE:
            return testType<test_array_type::DOUBLE>::type(tmp, 10);
    }
}

int main()
{
    char* tmp = new char[10];
    for (int i = 0; i < 10; i++) {
        tmp[i] = 'a' + i;
    }
    tmp[9] = '
#include <iostream>

using namespace std;

enum class test_array_type {
    CHARACTER,
    DOUBLE
};

template<typename T>
class arrayview {
    // yeah, you might think that why this class is needed,
    // I removed many member methods.
public:
    T* m_data;
    const int m_size;
    arrayview(T* data, int size) :m_data(data), m_size(size) {};
};

template<test_array_type T>
struct testType {
    using type = typename arrayview<double>;
};

template<>
struct testType<test_array_type::CHARACTER> {
    using type = typename arrayview<char>;
};

template<test_array_type ty>
testType<ty>::type get_type(void* tmp) {
    switch (ty) {
        case test_array_type::CHARACTER:
            return testType<test_array_type::CHARACTER>::type(tmp, 10);
        case test_array_type::DOUBLE:
            return testType<test_array_type::DOUBLE>::type(tmp, 10);
    }
}

int main()
{
    char* tmp = new char[10];
    for (int i = 0; i < 10; i++) {
        tmp[i] = 'a' + i;
    }
    tmp[9] = '\0';
    testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp));
    testType<test_array_type::CHARACTER>::type(tmp, 10);
    std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl;
    return 0;
}
'
;
testType<test_array_type::CHARACTER>::type ttt = get_type< test_array_type::CHARACTER>(reinterpret_cast<void*>(tmp)); testType<test_array_type::CHARACTER>::type(tmp, 10); std::cout << reinterpret_cast<char*>(ttt.m_data) << std::endl; return 0; }

How can I solve this problem?

If I remove all constructors except the default constructor, then it compiles. But that's not I want to make.

I think I misunderstand how the compiler and template rules and principles work.

英文:

I want to build a simple array data wrapper. It shows me a data what I suggested views (like double or character).

This function get_type() simply returns separate objects with enum tags (I used SIFNE).

So my expectation was, if some pointer (void* tmp) existed, when I call get_type&lt;CHARACTER&gt;(tmp, size) then function would return an arrayview&lt;char&gt; object.

But it isn't, it raises an error:

> c2440 ' function-style-cast ' cannot convert from 'initializer list' to

This is my full code of my test code (I simplified my problem):

#include &lt;iostream&gt;

using namespace std;

enum class test_array_type {
	CHARACTER,
	DOUBLE
};


template&lt;typename T&gt;
class arrayview {
	// yeah, you might think that why this class is needed, 
    // I removed many member methods. 
public:
	T* m_data;
	const int m_size;
	arrayview(T* data, int size) :m_data(data), m_size(size) {};
};

template&lt;test_array_type T&gt;
struct testType {
	using type = typename arrayview&lt;double&gt;;
};

template&lt;&gt;
struct testType&lt;test_array_type::CHARACTER&gt; {
	using type = typename arrayview&lt;char&gt;;
};

template&lt;test_array_type ty&gt;
testType&lt;ty&gt;::type get_type(void* tmp) {
	switch (ty) {
		case test_array_type::CHARACTER:
			return testType&lt;test_array_type::CHARACTER&gt;::type(tmp, 10);
		case test_array_type::DOUBLE:
			return testType&lt;test_array_type::DOUBLE&gt;::type(tmp, 10);
	}
}

int main()
{
	char* tmp = new char[10];
	for (int i = 0; i &lt; 10; i++) {
		tmp[i] = &#39;a&#39; + i;
	}
	tmp[9] = &#39;
#include &lt;iostream&gt;
using namespace std;
enum class test_array_type {
CHARACTER,
DOUBLE
};
template&lt;typename T&gt;
class arrayview {
// yeah, you might think that why this class is needed, 
// I removed many member methods. 
public:
T* m_data;
const int m_size;
arrayview(T* data, int size) :m_data(data), m_size(size) {};
};
template&lt;test_array_type T&gt;
struct testType {
using type = typename arrayview&lt;double&gt;;
};
template&lt;&gt;
struct testType&lt;test_array_type::CHARACTER&gt; {
using type = typename arrayview&lt;char&gt;;
};
template&lt;test_array_type ty&gt;
testType&lt;ty&gt;::type get_type(void* tmp) {
switch (ty) {
case test_array_type::CHARACTER:
return testType&lt;test_array_type::CHARACTER&gt;::type(tmp, 10);
case test_array_type::DOUBLE:
return testType&lt;test_array_type::DOUBLE&gt;::type(tmp, 10);
}
}
int main()
{
char* tmp = new char[10];
for (int i = 0; i &lt; 10; i++) {
tmp[i] = &#39;a&#39; + i;
}
tmp[9] = &#39;\0&#39;;
testType&lt;test_array_type::CHARACTER&gt;::type ttt = get_type&lt; test_array_type::CHARACTER&gt;(reinterpret_cast&lt;void*&gt;(tmp));
testType&lt;test_array_type::CHARACTER&gt;::type(tmp, 10);
std::cout &lt;&lt; reinterpret_cast&lt;char*&gt;(ttt.m_data) &lt;&lt; std::endl;
return 0;
}
&#39;; testType&lt;test_array_type::CHARACTER&gt;::type ttt = get_type&lt; test_array_type::CHARACTER&gt;(reinterpret_cast&lt;void*&gt;(tmp)); testType&lt;test_array_type::CHARACTER&gt;::type(tmp, 10); std::cout &lt;&lt; reinterpret_cast&lt;char*&gt;(ttt.m_data) &lt;&lt; std::endl; return 0; }

How can I solve this problem?

If I remove all constructors except the default constructor, then it compiles. But that's not I want to make.

I think I misunderstand how the compiler and template rules and principles work.

答案1

得分: 1

SIFNE是什么?你是不是指的是SFINAE(替代失败不是错误)?你的代码中没有SFINAE。

你的get_type()方法试图基于一个enum返回两个不相关的类型,但在C++中无法这样做。

而不是使用switch,你应该使用以下之一:

template<test_array_type ty>
auto get_type(void* tmp) {

    if constexpr (ty == test_array_type::CHARACTER) {
        return testType<test_array_type::CHARACTER>::type{tmp, 10};
    } else {
        return testType<test_array_type::DOUBLE>::type{tmp, 10};
    }

    // 或者简单地:
    // return testType<ty>::type{tmp, 10};
}
template<test_array_type ty>
void get_type(void*) {}

template<>
arrayview<char> get_type<test_array_type::CHARACTER>(void* tmp) {
    return arrayview<char>{tmp, 10};
}

template<>
arrayview<double> get_type<test_array_type::DOUBLE>(void* tmp) {
    return arrayview<double>{tmp, 10};
}
英文:

What is SIFNE? Did you mean SFINAE (Substitution Failure Is Not An Error)? There is no SFINAE in your code.

Your get_type() method is trying to return two unrelated types based on an enum, but you can't do that in C++.

Instead of using a switch, you should use either:

template&lt;test_array_type ty&gt;
auto get_type(void* tmp) {

    if constexpr (ty == test_array_type::CHARACTER) {
        return testType&lt;test_array_type::CHARACTER&gt;::type{tmp, 10};
    } else {
        return testType&lt;test_array_type::DOUBLE&gt;::type{tmp, 10};
    }

    // or simply:
    // return testType&lt;ty&gt;::type{tmp, 10};
}
template&lt;test_array_type ty&gt;
void get_type(void*) {}

template&lt;&gt;
arrayview&lt;char&gt; get_type&lt;test_array_type::CHARACTER&gt;(void* tmp) {
    return arrayview&lt;char&gt;{tmp, 10};
}

template&lt;&gt;
arrayview&lt;double&gt; get_type&lt;test_array_type::DOUBLE&gt;(void* tmp) {
    return arrayview&lt;double&gt;{tmp, 10};
}

huangapple
  • 本文由 发表于 2023年6月30日 03:50:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76584205.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定