Can template deduction guides call constexpr functions?
I have my own fixed-size array type I want to be constexpr
constructible from an std::initializer_list
without having to explicitly define the size template argument.
I thought I'd be able to use a template deduction guide but it looks like it's not treating std::initializer_list::size()
as a constexpr function for it.
Here's an example of trying to make a deduction guide for std::array
(which is similar to my type and has the same problem):
namespace std
{
template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};
I've tried on MSVC and Clang, both give roughly the same errors:
myArray
has an error complaining about too many arguments to the function.
myArray2
says "substitution failure [with T = int]: non-type template argument is not a constant expression"
I tried putting constexpr
in front of the deduction guide or the function argument but neither appears to be allowed, so it appears that the deduction guide is invalid even though it should work fine in a constexpr
context.
Is there a way to make this work without going down the make_array()
route?
c++ c++17 constexpr template-deduction
add a comment |
I have my own fixed-size array type I want to be constexpr
constructible from an std::initializer_list
without having to explicitly define the size template argument.
I thought I'd be able to use a template deduction guide but it looks like it's not treating std::initializer_list::size()
as a constexpr function for it.
Here's an example of trying to make a deduction guide for std::array
(which is similar to my type and has the same problem):
namespace std
{
template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};
I've tried on MSVC and Clang, both give roughly the same errors:
myArray
has an error complaining about too many arguments to the function.
myArray2
says "substitution failure [with T = int]: non-type template argument is not a constant expression"
I tried putting constexpr
in front of the deduction guide or the function argument but neither appears to be allowed, so it appears that the deduction guide is invalid even though it should work fine in a constexpr
context.
Is there a way to make this work without going down the make_array()
route?
c++ c++17 constexpr template-deduction
add a comment |
I have my own fixed-size array type I want to be constexpr
constructible from an std::initializer_list
without having to explicitly define the size template argument.
I thought I'd be able to use a template deduction guide but it looks like it's not treating std::initializer_list::size()
as a constexpr function for it.
Here's an example of trying to make a deduction guide for std::array
(which is similar to my type and has the same problem):
namespace std
{
template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};
I've tried on MSVC and Clang, both give roughly the same errors:
myArray
has an error complaining about too many arguments to the function.
myArray2
says "substitution failure [with T = int]: non-type template argument is not a constant expression"
I tried putting constexpr
in front of the deduction guide or the function argument but neither appears to be allowed, so it appears that the deduction guide is invalid even though it should work fine in a constexpr
context.
Is there a way to make this work without going down the make_array()
route?
c++ c++17 constexpr template-deduction
I have my own fixed-size array type I want to be constexpr
constructible from an std::initializer_list
without having to explicitly define the size template argument.
I thought I'd be able to use a template deduction guide but it looks like it's not treating std::initializer_list::size()
as a constexpr function for it.
Here's an example of trying to make a deduction guide for std::array
(which is similar to my type and has the same problem):
namespace std
{
template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};
I've tried on MSVC and Clang, both give roughly the same errors:
myArray
has an error complaining about too many arguments to the function.
myArray2
says "substitution failure [with T = int]: non-type template argument is not a constant expression"
I tried putting constexpr
in front of the deduction guide or the function argument but neither appears to be allowed, so it appears that the deduction guide is invalid even though it should work fine in a constexpr
context.
Is there a way to make this work without going down the make_array()
route?
c++ c++17 constexpr template-deduction
c++ c++17 constexpr template-deduction
edited 6 hours ago
max66
34.6k63762
34.6k63762
asked 6 hours ago
Blake Preston
563
563
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
You can do:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
The problem is not that you cannot call constexpr
functions in deduction guides. You can. This example is ridiculous, but works:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
The problem is that function parameters are not constexpr
objects, so you cannot invoke constexpr
member functions on them if those member functions read kind of local state.
add a comment |
Is there a way to make this work without going down the
make_array()
route?
Why don't you try with the following deduction guide ?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
This way, the argument in myArray2 = {{1,2,3}}
isn't interpreted as a std::initializer_list
(that as argument can't be considered constexpr
, so it's size()
can't be used for a template argument) but as a C-style array.
So can be deduced, as template arguments, type and size (T
and N
) and also the size (N
) can be used as template argument.
add a comment |
Parameter/argument values are not constexpr
.
You might use variadic template to know size at compile time, or type with know size (std::array
or C-array reference).
add a comment |
I have tried these:
namespace std {
template<typename... T>
array( T... ) -> array<T..., sizeof...(T)>;
/*
template<typename... T>
array( initializer_list<T...> ) -> array<T..., sizeof...(T)>;
*/
}
static constexpr std::array myArray = { 1,2,3 };
static constexpr std::array myArray2 { 1,2,3,4 };
int main() {
for ( auto& n : myArray )
std::cout << n << ' ';
std::cout << 'n';
for ( auto& n2 : myArray2 )
std::cout << n2 << ' ';
std::cout << 'n';
return 0;
}
And I got the output:
1 2 3
1 2 3 4
However when I tried these:
static constexpr std::array myArray3 = { {1,2,3} };
static constexpr std::array myArray4 { {1,2,3} };
It had failed to compile.
I believe this is mimicking the behavior that you are after, however I'm not using initializer_list
directly, I'm just using the properties of variadic templates to construct the array along with the ...sizeof()
operator.
down vote and no explanation of why?
– Francis Cugler
2 hours ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54066651%2fcan-template-deduction-guides-call-constexpr-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can do:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
The problem is not that you cannot call constexpr
functions in deduction guides. You can. This example is ridiculous, but works:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
The problem is that function parameters are not constexpr
objects, so you cannot invoke constexpr
member functions on them if those member functions read kind of local state.
add a comment |
You can do:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
The problem is not that you cannot call constexpr
functions in deduction guides. You can. This example is ridiculous, but works:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
The problem is that function parameters are not constexpr
objects, so you cannot invoke constexpr
member functions on them if those member functions read kind of local state.
add a comment |
You can do:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
The problem is not that you cannot call constexpr
functions in deduction guides. You can. This example is ridiculous, but works:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
The problem is that function parameters are not constexpr
objects, so you cannot invoke constexpr
member functions on them if those member functions read kind of local state.
You can do:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
The problem is not that you cannot call constexpr
functions in deduction guides. You can. This example is ridiculous, but works:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
The problem is that function parameters are not constexpr
objects, so you cannot invoke constexpr
member functions on them if those member functions read kind of local state.
answered 6 hours ago
Barry
177k18304561
177k18304561
add a comment |
add a comment |
Is there a way to make this work without going down the
make_array()
route?
Why don't you try with the following deduction guide ?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
This way, the argument in myArray2 = {{1,2,3}}
isn't interpreted as a std::initializer_list
(that as argument can't be considered constexpr
, so it's size()
can't be used for a template argument) but as a C-style array.
So can be deduced, as template arguments, type and size (T
and N
) and also the size (N
) can be used as template argument.
add a comment |
Is there a way to make this work without going down the
make_array()
route?
Why don't you try with the following deduction guide ?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
This way, the argument in myArray2 = {{1,2,3}}
isn't interpreted as a std::initializer_list
(that as argument can't be considered constexpr
, so it's size()
can't be used for a template argument) but as a C-style array.
So can be deduced, as template arguments, type and size (T
and N
) and also the size (N
) can be used as template argument.
add a comment |
Is there a way to make this work without going down the
make_array()
route?
Why don't you try with the following deduction guide ?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
This way, the argument in myArray2 = {{1,2,3}}
isn't interpreted as a std::initializer_list
(that as argument can't be considered constexpr
, so it's size()
can't be used for a template argument) but as a C-style array.
So can be deduced, as template arguments, type and size (T
and N
) and also the size (N
) can be used as template argument.
Is there a way to make this work without going down the
make_array()
route?
Why don't you try with the following deduction guide ?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
This way, the argument in myArray2 = {{1,2,3}}
isn't interpreted as a std::initializer_list
(that as argument can't be considered constexpr
, so it's size()
can't be used for a template argument) but as a C-style array.
So can be deduced, as template arguments, type and size (T
and N
) and also the size (N
) can be used as template argument.
edited 3 hours ago
answered 6 hours ago
max66
34.6k63762
34.6k63762
add a comment |
add a comment |
Parameter/argument values are not constexpr
.
You might use variadic template to know size at compile time, or type with know size (std::array
or C-array reference).
add a comment |
Parameter/argument values are not constexpr
.
You might use variadic template to know size at compile time, or type with know size (std::array
or C-array reference).
add a comment |
Parameter/argument values are not constexpr
.
You might use variadic template to know size at compile time, or type with know size (std::array
or C-array reference).
Parameter/argument values are not constexpr
.
You might use variadic template to know size at compile time, or type with know size (std::array
or C-array reference).
answered 6 hours ago
Jarod42
113k12101181
113k12101181
add a comment |
add a comment |
I have tried these:
namespace std {
template<typename... T>
array( T... ) -> array<T..., sizeof...(T)>;
/*
template<typename... T>
array( initializer_list<T...> ) -> array<T..., sizeof...(T)>;
*/
}
static constexpr std::array myArray = { 1,2,3 };
static constexpr std::array myArray2 { 1,2,3,4 };
int main() {
for ( auto& n : myArray )
std::cout << n << ' ';
std::cout << 'n';
for ( auto& n2 : myArray2 )
std::cout << n2 << ' ';
std::cout << 'n';
return 0;
}
And I got the output:
1 2 3
1 2 3 4
However when I tried these:
static constexpr std::array myArray3 = { {1,2,3} };
static constexpr std::array myArray4 { {1,2,3} };
It had failed to compile.
I believe this is mimicking the behavior that you are after, however I'm not using initializer_list
directly, I'm just using the properties of variadic templates to construct the array along with the ...sizeof()
operator.
down vote and no explanation of why?
– Francis Cugler
2 hours ago
add a comment |
I have tried these:
namespace std {
template<typename... T>
array( T... ) -> array<T..., sizeof...(T)>;
/*
template<typename... T>
array( initializer_list<T...> ) -> array<T..., sizeof...(T)>;
*/
}
static constexpr std::array myArray = { 1,2,3 };
static constexpr std::array myArray2 { 1,2,3,4 };
int main() {
for ( auto& n : myArray )
std::cout << n << ' ';
std::cout << 'n';
for ( auto& n2 : myArray2 )
std::cout << n2 << ' ';
std::cout << 'n';
return 0;
}
And I got the output:
1 2 3
1 2 3 4
However when I tried these:
static constexpr std::array myArray3 = { {1,2,3} };
static constexpr std::array myArray4 { {1,2,3} };
It had failed to compile.
I believe this is mimicking the behavior that you are after, however I'm not using initializer_list
directly, I'm just using the properties of variadic templates to construct the array along with the ...sizeof()
operator.
down vote and no explanation of why?
– Francis Cugler
2 hours ago
add a comment |
I have tried these:
namespace std {
template<typename... T>
array( T... ) -> array<T..., sizeof...(T)>;
/*
template<typename... T>
array( initializer_list<T...> ) -> array<T..., sizeof...(T)>;
*/
}
static constexpr std::array myArray = { 1,2,3 };
static constexpr std::array myArray2 { 1,2,3,4 };
int main() {
for ( auto& n : myArray )
std::cout << n << ' ';
std::cout << 'n';
for ( auto& n2 : myArray2 )
std::cout << n2 << ' ';
std::cout << 'n';
return 0;
}
And I got the output:
1 2 3
1 2 3 4
However when I tried these:
static constexpr std::array myArray3 = { {1,2,3} };
static constexpr std::array myArray4 { {1,2,3} };
It had failed to compile.
I believe this is mimicking the behavior that you are after, however I'm not using initializer_list
directly, I'm just using the properties of variadic templates to construct the array along with the ...sizeof()
operator.
I have tried these:
namespace std {
template<typename... T>
array( T... ) -> array<T..., sizeof...(T)>;
/*
template<typename... T>
array( initializer_list<T...> ) -> array<T..., sizeof...(T)>;
*/
}
static constexpr std::array myArray = { 1,2,3 };
static constexpr std::array myArray2 { 1,2,3,4 };
int main() {
for ( auto& n : myArray )
std::cout << n << ' ';
std::cout << 'n';
for ( auto& n2 : myArray2 )
std::cout << n2 << ' ';
std::cout << 'n';
return 0;
}
And I got the output:
1 2 3
1 2 3 4
However when I tried these:
static constexpr std::array myArray3 = { {1,2,3} };
static constexpr std::array myArray4 { {1,2,3} };
It had failed to compile.
I believe this is mimicking the behavior that you are after, however I'm not using initializer_list
directly, I'm just using the properties of variadic templates to construct the array along with the ...sizeof()
operator.
answered 3 hours ago
Francis Cugler
4,40811227
4,40811227
down vote and no explanation of why?
– Francis Cugler
2 hours ago
add a comment |
down vote and no explanation of why?
– Francis Cugler
2 hours ago
down vote and no explanation of why?
– Francis Cugler
2 hours ago
down vote and no explanation of why?
– Francis Cugler
2 hours ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54066651%2fcan-template-deduction-guides-call-constexpr-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown